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 */
211193Smws
220Sstevel@tonic-gate /*
239874SStephen.Hanson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <strings.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <netdir.h>
300Sstevel@tonic-gate #include <errno.h>
311303Swesolows #include <alloca.h>
321303Swesolows #include <locale.h>
331303Swesolows #include <uuid/uuid.h>
340Sstevel@tonic-gate
351303Swesolows #include <sys/fm/protocol.h>
360Sstevel@tonic-gate #include <fmd_adm_impl.h>
370Sstevel@tonic-gate #include <fmd_rpc_adm.h>
380Sstevel@tonic-gate
390Sstevel@tonic-gate static const uint_t _fmd_adm_bufsize = 128 * 1024;
401303Swesolows static const char _url_fallback[] = "http://sun.com/msg/";
410Sstevel@tonic-gate
420Sstevel@tonic-gate fmd_adm_t *
fmd_adm_open(const char * host,uint32_t prog,int version)430Sstevel@tonic-gate fmd_adm_open(const char *host, uint32_t prog, int version)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate fmd_adm_t *ap;
460Sstevel@tonic-gate CLIENT *c;
470Sstevel@tonic-gate rpcvers_t v;
480Sstevel@tonic-gate
490Sstevel@tonic-gate if (version != FMD_ADM_VERSION) {
500Sstevel@tonic-gate errno = ENOTSUP;
510Sstevel@tonic-gate return (NULL);
520Sstevel@tonic-gate }
530Sstevel@tonic-gate
540Sstevel@tonic-gate if (host == NULL)
550Sstevel@tonic-gate host = HOST_SELF;
560Sstevel@tonic-gate
570Sstevel@tonic-gate if (prog == FMD_ADM_PROGRAM)
580Sstevel@tonic-gate prog = FMD_ADM;
590Sstevel@tonic-gate
607238Seschrock if ((ap = malloc(sizeof (fmd_adm_t))) == NULL)
617238Seschrock return (NULL);
627238Seschrock
637238Seschrock if (strcmp(host, HOST_SELF) == 0) {
640Sstevel@tonic-gate c = clnt_door_create(prog, FMD_ADM_VERSION_1, _fmd_adm_bufsize);
657238Seschrock ap->adm_maxretries = 1;
667238Seschrock } else {
670Sstevel@tonic-gate c = clnt_create_vers(host, prog, &v,
680Sstevel@tonic-gate FMD_ADM_VERSION_1, FMD_ADM_VERSION_1, NULL);
697238Seschrock ap->adm_maxretries = 0;
700Sstevel@tonic-gate }
710Sstevel@tonic-gate
720Sstevel@tonic-gate if (c == NULL) {
730Sstevel@tonic-gate errno = EPROTO;
747238Seschrock free(ap);
750Sstevel@tonic-gate return (NULL);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
787238Seschrock ap->adm_prog = prog;
790Sstevel@tonic-gate ap->adm_clnt = c;
800Sstevel@tonic-gate ap->adm_version = version;
810Sstevel@tonic-gate ap->adm_svcerr = 0;
820Sstevel@tonic-gate ap->adm_errno = 0;
830Sstevel@tonic-gate
840Sstevel@tonic-gate return (ap);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate void
fmd_adm_close(fmd_adm_t * ap)880Sstevel@tonic-gate fmd_adm_close(fmd_adm_t *ap)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate if (ap == NULL)
910Sstevel@tonic-gate return; /* permit NULL to simply caller code */
920Sstevel@tonic-gate
930Sstevel@tonic-gate clnt_destroy(ap->adm_clnt);
940Sstevel@tonic-gate free(ap);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate static const char *
fmd_adm_svc_errmsg(enum fmd_adm_error err)980Sstevel@tonic-gate fmd_adm_svc_errmsg(enum fmd_adm_error err)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate switch (err) {
1010Sstevel@tonic-gate case FMD_ADM_ERR_NOMEM:
1020Sstevel@tonic-gate return ("unable to perform request due to allocation failure");
1030Sstevel@tonic-gate case FMD_ADM_ERR_PERM:
1040Sstevel@tonic-gate return ("operation requires additional privilege");
1050Sstevel@tonic-gate case FMD_ADM_ERR_MODSRCH:
1060Sstevel@tonic-gate return ("specified module is not loaded in fault manager");
1070Sstevel@tonic-gate case FMD_ADM_ERR_MODBUSY:
1080Sstevel@tonic-gate return ("module is in use and cannot be unloaded");
1090Sstevel@tonic-gate case FMD_ADM_ERR_MODFAIL:
1100Sstevel@tonic-gate return ("module failed and can no longer export statistics");
1110Sstevel@tonic-gate case FMD_ADM_ERR_MODNOENT:
1120Sstevel@tonic-gate return ("file missing or cannot be accessed by fault manager");
1130Sstevel@tonic-gate case FMD_ADM_ERR_MODEXIST:
1140Sstevel@tonic-gate return ("module using same name is already loaded");
1150Sstevel@tonic-gate case FMD_ADM_ERR_MODINIT:
1160Sstevel@tonic-gate return ("module failed to initialize (consult fmd(1M) log)");
1170Sstevel@tonic-gate case FMD_ADM_ERR_MODLOAD:
1180Sstevel@tonic-gate return ("module failed to load (consult fmd(1M) log)");
1190Sstevel@tonic-gate case FMD_ADM_ERR_RSRCSRCH:
1200Sstevel@tonic-gate return ("specified resource is not cached by fault manager");
1210Sstevel@tonic-gate case FMD_ADM_ERR_RSRCNOTF:
1220Sstevel@tonic-gate return ("specified resource is not known to be faulty");
1230Sstevel@tonic-gate case FMD_ADM_ERR_SERDSRCH:
1240Sstevel@tonic-gate return ("specified serd engine not present in module");
1250Sstevel@tonic-gate case FMD_ADM_ERR_SERDFIRED:
1260Sstevel@tonic-gate return ("specified serd engine has already fired");
1270Sstevel@tonic-gate case FMD_ADM_ERR_ROTSRCH:
1280Sstevel@tonic-gate return ("invalid log file name");
1290Sstevel@tonic-gate case FMD_ADM_ERR_ROTFAIL:
1300Sstevel@tonic-gate return ("failed to rotate log file (consult fmd(1M) log)");
1310Sstevel@tonic-gate case FMD_ADM_ERR_ROTBUSY:
1320Sstevel@tonic-gate return ("log file is too busy to rotate (try again later)");
1330Sstevel@tonic-gate case FMD_ADM_ERR_CASESRCH:
1340Sstevel@tonic-gate return ("specified UUID is invalid or has been repaired");
1350Sstevel@tonic-gate case FMD_ADM_ERR_CASEOPEN:
1360Sstevel@tonic-gate return ("specified UUID is still being diagnosed");
1371193Smws case FMD_ADM_ERR_XPRTSRCH:
1381193Smws return ("specified transport ID is invalid or has been closed");
1391193Smws case FMD_ADM_ERR_CASEXPRT:
1401193Smws return ("specified UUID is owned by a different fault manager");
1419874SStephen.Hanson@Sun.COM case FMD_ADM_ERR_RSRCNOTR:
1429874SStephen.Hanson@Sun.COM return ("specified resource has not been replaced");
1430Sstevel@tonic-gate default:
1440Sstevel@tonic-gate return ("unknown fault manager error");
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate const char *
fmd_adm_errmsg(fmd_adm_t * ap)1490Sstevel@tonic-gate fmd_adm_errmsg(fmd_adm_t *ap)
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate if (ap == NULL) {
1520Sstevel@tonic-gate switch (errno) {
1530Sstevel@tonic-gate case ENOTSUP:
1540Sstevel@tonic-gate return ("client requires newer libfmd_adm version");
1550Sstevel@tonic-gate case EPROTO:
1560Sstevel@tonic-gate return (clnt_spcreateerror("failed to connect to fmd"));
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate switch (ap ? ap->adm_errno : errno) {
1610Sstevel@tonic-gate case EPROTO:
1620Sstevel@tonic-gate return (clnt_sperror(ap->adm_clnt, "rpc call failed"));
1630Sstevel@tonic-gate case EREMOTE:
1640Sstevel@tonic-gate return (fmd_adm_svc_errmsg(ap->adm_svcerr));
1650Sstevel@tonic-gate default:
1660Sstevel@tonic-gate return (strerror(ap->adm_errno));
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate static int
fmd_adm_set_svcerr(fmd_adm_t * ap,enum fmd_adm_error err)1710Sstevel@tonic-gate fmd_adm_set_svcerr(fmd_adm_t *ap, enum fmd_adm_error err)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate if (err != 0) {
1740Sstevel@tonic-gate ap->adm_svcerr = err;
1750Sstevel@tonic-gate ap->adm_errno = EREMOTE;
1760Sstevel@tonic-gate return (-1);
1770Sstevel@tonic-gate } else {
1780Sstevel@tonic-gate ap->adm_svcerr = err;
1790Sstevel@tonic-gate ap->adm_errno = 0;
1800Sstevel@tonic-gate return (0);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate static int
fmd_adm_set_errno(fmd_adm_t * ap,int err)1850Sstevel@tonic-gate fmd_adm_set_errno(fmd_adm_t *ap, int err)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate ap->adm_errno = err;
1880Sstevel@tonic-gate errno = err;
1890Sstevel@tonic-gate return (-1);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate static int
fmd_adm_stats_cmp(const void * lp,const void * rp)1930Sstevel@tonic-gate fmd_adm_stats_cmp(const void *lp, const void *rp)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate return (strcmp(((fmd_stat_t *)lp)->fmds_name,
1960Sstevel@tonic-gate ((fmd_stat_t *)rp)->fmds_name));
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate
1997238Seschrock /*
2007238Seschrock * If the server (fmd) is restarted, this will cause all future door calls to
2017238Seschrock * fail. Unfortunately, once the server comes back up, we have no way of
2027238Seschrock * reestablishing the connection. To get around this, if the error indicates
2037238Seschrock * that the RPC call failed, we reopen the client handle and try again. For
2047238Seschrock * simplicity we only deal with the door case, as it's unclear whether the
2057238Seschrock * remote case suffers from the same pathology.
2067238Seschrock */
2077238Seschrock boolean_t
fmd_adm_retry(fmd_adm_t * ap,enum clnt_stat cs,uint_t * retries)2087238Seschrock fmd_adm_retry(fmd_adm_t *ap, enum clnt_stat cs, uint_t *retries)
2097238Seschrock {
2107238Seschrock CLIENT *c;
2117238Seschrock struct rpc_err err;
2127238Seschrock
2137238Seschrock if (cs == RPC_SUCCESS || *retries == ap->adm_maxretries)
2147238Seschrock return (B_FALSE);
2157238Seschrock
2167238Seschrock clnt_geterr(ap->adm_clnt, &err);
2177238Seschrock if (err.re_status != RPC_CANTSEND)
2187238Seschrock return (B_FALSE);
2197238Seschrock
2207238Seschrock if ((c = clnt_door_create(ap->adm_prog, FMD_ADM_VERSION_1,
2217238Seschrock _fmd_adm_bufsize)) == NULL)
2227238Seschrock return (B_FALSE);
2237238Seschrock
2247238Seschrock (*retries)++;
2257238Seschrock
2267238Seschrock clnt_destroy(ap->adm_clnt);
2277238Seschrock ap->adm_clnt = c;
2287238Seschrock
2297238Seschrock return (B_TRUE);
2307238Seschrock }
2317238Seschrock
2320Sstevel@tonic-gate int
fmd_adm_stats_read(fmd_adm_t * ap,const char * name,fmd_adm_stats_t * sp)2330Sstevel@tonic-gate fmd_adm_stats_read(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate struct fmd_rpc_modstat rms;
2360Sstevel@tonic-gate enum clnt_stat cs;
2377238Seschrock uint_t retries = 0;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (sp == NULL)
2400Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
2430Sstevel@tonic-gate
2447238Seschrock do {
2457238Seschrock if (name != NULL)
2467238Seschrock cs = fmd_adm_modcstat_1((char *)name, &rms,
2477238Seschrock ap->adm_clnt);
2487238Seschrock else
2497238Seschrock cs = fmd_adm_modgstat_1(&rms, ap->adm_clnt);
2507238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate if (cs != RPC_SUCCESS)
2530Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate if (rms.rms_err != 0) {
2560Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
2570Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rms.rms_err));
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate sp->ams_buf = rms.rms_buf.rms_buf_val;
2610Sstevel@tonic-gate sp->ams_len = rms.rms_buf.rms_buf_len;
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate if (sp->ams_len != 0) {
2640Sstevel@tonic-gate qsort(sp->ams_buf, sp->ams_len,
2650Sstevel@tonic-gate sizeof (fmd_stat_t), fmd_adm_stats_cmp);
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate return (0);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate int
fmd_adm_stats_free(fmd_adm_t * ap,fmd_adm_stats_t * sp)2720Sstevel@tonic-gate fmd_adm_stats_free(fmd_adm_t *ap, fmd_adm_stats_t *sp)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate struct fmd_rpc_modstat rms;
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate if (sp == NULL)
2770Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate rms.rms_buf.rms_buf_val = sp->ams_buf;
2800Sstevel@tonic-gate rms.rms_buf.rms_buf_len = sp->ams_len;
2810Sstevel@tonic-gate rms.rms_err = 0;
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
2840Sstevel@tonic-gate bzero(sp, sizeof (fmd_adm_stats_t));
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate return (0);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate static int
fmd_adm_module_cmp(const void * lp,const void * rp)2900Sstevel@tonic-gate fmd_adm_module_cmp(const void *lp, const void *rp)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate return (strcmp((*(struct fmd_rpc_modinfo **)lp)->rmi_name,
2930Sstevel@tonic-gate (*(struct fmd_rpc_modinfo **)rp)->rmi_name));
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate int
fmd_adm_module_iter(fmd_adm_t * ap,fmd_adm_module_f * func,void * arg)2970Sstevel@tonic-gate fmd_adm_module_iter(fmd_adm_t *ap, fmd_adm_module_f *func, void *arg)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate struct fmd_rpc_modinfo *rmi, **rms, **rmp;
3000Sstevel@tonic-gate struct fmd_rpc_modlist rml;
3010Sstevel@tonic-gate fmd_adm_modinfo_t ami;
3027238Seschrock enum clnt_stat cs;
3037238Seschrock uint_t retries = 0;
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate bzero(&rml, sizeof (rml)); /* tell xdr to allocate memory for us */
3060Sstevel@tonic-gate
3077238Seschrock do {
3087238Seschrock cs = fmd_adm_modinfo_1(&rml, ap->adm_clnt);
3097238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
3107238Seschrock
3117238Seschrock if (cs != RPC_SUCCESS)
3120Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate if (rml.rml_err != 0 || rml.rml_len == 0) {
3150Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3160Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rml.rml_err));
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate if ((rms = rmp = malloc(sizeof (void *) * rml.rml_len)) == NULL) {
3200Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3210Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EAGAIN));
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate for (rmi = rml.rml_list; rmi != NULL; rmi = rmi->rmi_next)
3250Sstevel@tonic-gate *rmp++ = rmi; /* store copy of pointer in array for sorting */
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate qsort(rms, rml.rml_len, sizeof (void *), fmd_adm_module_cmp);
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate for (rmp = rms; rmp < rms + rml.rml_len; rmp++) {
3300Sstevel@tonic-gate rmi = *rmp;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate ami.ami_name = rmi->rmi_name;
3330Sstevel@tonic-gate ami.ami_desc = rmi->rmi_desc;
3340Sstevel@tonic-gate ami.ami_vers = rmi->rmi_vers;
3350Sstevel@tonic-gate ami.ami_flags = 0;
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate if (rmi->rmi_faulty)
3380Sstevel@tonic-gate ami.ami_flags |= FMD_ADM_MOD_FAILED;
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate if (func(&ami, arg) != 0)
3410Sstevel@tonic-gate break;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate free(rms);
3450Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3460Sstevel@tonic-gate return (0);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate int
fmd_adm_module_load(fmd_adm_t * ap,const char * path)3500Sstevel@tonic-gate fmd_adm_module_load(fmd_adm_t *ap, const char *path)
3510Sstevel@tonic-gate {
3520Sstevel@tonic-gate char *str = (char *)path;
3530Sstevel@tonic-gate int err;
3547238Seschrock enum clnt_stat cs;
3557238Seschrock uint_t retries = 0;
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate if (path == NULL || path[0] != '/')
3580Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
3590Sstevel@tonic-gate
3607238Seschrock do {
3617238Seschrock cs = fmd_adm_modload_1(str, &err, ap->adm_clnt);
3627238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
3637238Seschrock
3647238Seschrock if (cs != RPC_SUCCESS)
3650Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate int
fmd_adm_module_unload(fmd_adm_t * ap,const char * name)3710Sstevel@tonic-gate fmd_adm_module_unload(fmd_adm_t *ap, const char *name)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate char *str = (char *)name;
3740Sstevel@tonic-gate int err;
3757238Seschrock enum clnt_stat cs;
3767238Seschrock uint_t retries = 0;
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate if (name == NULL || strchr(name, '/') != NULL)
3790Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
3800Sstevel@tonic-gate
3817238Seschrock do {
3827238Seschrock cs = fmd_adm_modunload_1(str, &err, ap->adm_clnt);
3837238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
3847238Seschrock
3857238Seschrock if (cs != RPC_SUCCESS)
3860Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate int
fmd_adm_module_reset(fmd_adm_t * ap,const char * name)3920Sstevel@tonic-gate fmd_adm_module_reset(fmd_adm_t *ap, const char *name)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate char *str = (char *)name;
3950Sstevel@tonic-gate int err;
3967238Seschrock enum clnt_stat cs;
3977238Seschrock uint_t retries = 0;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (name == NULL || strchr(name, '/') != NULL)
4000Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
4010Sstevel@tonic-gate
4027238Seschrock do {
4037238Seschrock cs = fmd_adm_modreset_1(str, &err, ap->adm_clnt);
4047238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
4057238Seschrock
4067238Seschrock if (cs != RPC_SUCCESS)
4070Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate int
fmd_adm_module_gc(fmd_adm_t * ap,const char * name)4130Sstevel@tonic-gate fmd_adm_module_gc(fmd_adm_t *ap, const char *name)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate char *str = (char *)name;
4160Sstevel@tonic-gate int err;
4177238Seschrock enum clnt_stat cs;
4187238Seschrock uint_t retries = 0;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate if (name == NULL || strchr(name, '/') != NULL)
4210Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
4220Sstevel@tonic-gate
4237238Seschrock do {
4247238Seschrock cs = fmd_adm_modgc_1(str, &err, ap->adm_clnt);
4257238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
4267238Seschrock
4277238Seschrock if (cs != RPC_SUCCESS)
4280Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate int
fmd_adm_module_stats(fmd_adm_t * ap,const char * name,fmd_adm_stats_t * sp)4340Sstevel@tonic-gate fmd_adm_module_stats(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
4350Sstevel@tonic-gate {
4360Sstevel@tonic-gate struct fmd_rpc_modstat rms;
4377238Seschrock enum clnt_stat cs;
4387238Seschrock uint_t retries = 0;
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate if (name == NULL || sp == NULL)
4410Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
4440Sstevel@tonic-gate
4457238Seschrock do {
4467238Seschrock cs = fmd_adm_moddstat_1((char *)name, &rms, ap->adm_clnt);
4477238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
4487238Seschrock
4497238Seschrock if (cs != RPC_SUCCESS)
4500Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate if (rms.rms_err != 0) {
4530Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
4540Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rms.rms_err));
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate sp->ams_buf = rms.rms_buf.rms_buf_val;
4580Sstevel@tonic-gate sp->ams_len = rms.rms_buf.rms_buf_len;
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate return (0);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate
4631303Swesolows int
fmd_adm_rsrc_count(fmd_adm_t * ap,int all,uint32_t * rcp)4641303Swesolows fmd_adm_rsrc_count(fmd_adm_t *ap, int all, uint32_t *rcp)
4651303Swesolows {
4661303Swesolows struct fmd_rpc_rsrclist rrl;
4677238Seschrock enum clnt_stat cs;
4687238Seschrock uint_t retries = 0;
4691303Swesolows
4701303Swesolows if (rcp == NULL)
4711303Swesolows return (fmd_adm_set_errno(ap, EINVAL));
4721303Swesolows
4731303Swesolows bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */
4741303Swesolows
4757238Seschrock do {
4767238Seschrock cs = fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt);
4777238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
4787238Seschrock
4797238Seschrock if (cs != RPC_SUCCESS)
4801303Swesolows return (fmd_adm_set_errno(ap, EPROTO));
4811303Swesolows
4821303Swesolows if (rrl.rrl_err != 0) {
4831303Swesolows xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
4841303Swesolows return (fmd_adm_set_svcerr(ap, rrl.rrl_err));
4851303Swesolows }
4861303Swesolows
4871303Swesolows *rcp = rrl.rrl_cnt;
4881303Swesolows xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
4891303Swesolows return (0);
4901303Swesolows }
4911303Swesolows
4920Sstevel@tonic-gate static int
fmd_adm_rsrc_cmp(const void * lp,const void * rp)4930Sstevel@tonic-gate fmd_adm_rsrc_cmp(const void *lp, const void *rp)
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate return (strcmp(*(char **)lp, *(char **)rp));
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate int
fmd_adm_rsrc_iter(fmd_adm_t * ap,int all,fmd_adm_rsrc_f * func,void * arg)4990Sstevel@tonic-gate fmd_adm_rsrc_iter(fmd_adm_t *ap, int all, fmd_adm_rsrc_f *func, void *arg)
5000Sstevel@tonic-gate {
5010Sstevel@tonic-gate struct fmd_rpc_rsrclist rrl;
5020Sstevel@tonic-gate struct fmd_rpc_rsrcinfo rri;
5030Sstevel@tonic-gate fmd_adm_rsrcinfo_t ari;
5040Sstevel@tonic-gate char **fmris, *p;
5050Sstevel@tonic-gate int i, rv;
5067238Seschrock enum clnt_stat cs;
5077238Seschrock uint_t retries = 0;
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */
5100Sstevel@tonic-gate
5117238Seschrock do {
5127238Seschrock cs = fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt);
5137238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
5147238Seschrock
5157238Seschrock if (cs != RPC_SUCCESS)
5160Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate if (rrl.rrl_err != 0) {
5190Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5200Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rrl.rrl_err));
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate if ((fmris = malloc(sizeof (char *) * rrl.rrl_cnt)) == NULL) {
5240Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5250Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EAGAIN));
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * The fmd_adm_rsrclist_1 request returns an opaque XDR buffer that is
5300Sstevel@tonic-gate * a string table of FMRIs (e.g. "fmriA\0fmriB\0...") where rrl_cnt is
5310Sstevel@tonic-gate * the number of strings in the table and rrl_buf_val is its address.
5320Sstevel@tonic-gate * We construct an array of pointers into the string table and sort it.
5330Sstevel@tonic-gate */
5340Sstevel@tonic-gate p = rrl.rrl_buf.rrl_buf_val;
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate for (i = 0; i < rrl.rrl_cnt; i++, p += strlen(p) + 1)
5370Sstevel@tonic-gate fmris[i] = p; /* store fmri pointer in array for sorting */
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate qsort(fmris, rrl.rrl_cnt, sizeof (char *), fmd_adm_rsrc_cmp);
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate * For each FMRI in the resource cache snapshot, use fmd_adm_rsrcinfo_1
5430Sstevel@tonic-gate * to get more information and the invoke the callback function. If
5440Sstevel@tonic-gate * FMD_ADM_ERR_RSRCSRCH is returned, the FMRI has been purged from the
5450Sstevel@tonic-gate * cache since our snapshot: this error is therefore silently ignored.
5460Sstevel@tonic-gate */
5470Sstevel@tonic-gate for (i = 0; i < rrl.rrl_cnt; i++) {
5480Sstevel@tonic-gate bzero(&rri, sizeof (rri));
5490Sstevel@tonic-gate
5507238Seschrock retries = 0;
5517238Seschrock do {
5527238Seschrock cs = fmd_adm_rsrcinfo_1(fmris[i], &rri, ap->adm_clnt);
5537238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
5547238Seschrock
5557238Seschrock if (cs != RPC_SUCCESS) {
5560Sstevel@tonic-gate free(fmris);
5570Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5580Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate if (rri.rri_err != 0 && rri.rri_err != FMD_ADM_ERR_RSRCSRCH) {
5620Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5630Sstevel@tonic-gate free(fmris);
5640Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5650Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rri.rri_err));
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate if (rri.rri_err == FMD_ADM_ERR_RSRCSRCH) {
5690Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5700Sstevel@tonic-gate continue;
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate ari.ari_fmri = rri.rri_fmri;
5740Sstevel@tonic-gate ari.ari_uuid = rri.rri_uuid;
5750Sstevel@tonic-gate ari.ari_case = rri.rri_case;
5760Sstevel@tonic-gate ari.ari_flags = 0;
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate if (rri.rri_faulty)
5790Sstevel@tonic-gate ari.ari_flags |= FMD_ADM_RSRC_FAULTY;
5800Sstevel@tonic-gate if (rri.rri_unusable)
5810Sstevel@tonic-gate ari.ari_flags |= FMD_ADM_RSRC_UNUSABLE;
5820Sstevel@tonic-gate if (rri.rri_invisible)
5830Sstevel@tonic-gate ari.ari_flags |= FMD_ADM_RSRC_INVISIBLE;
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate rv = func(&ari, arg);
5860Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate if (rv != 0)
5890Sstevel@tonic-gate break;
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate free(fmris);
5930Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5940Sstevel@tonic-gate return (0);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate int
fmd_adm_rsrc_flush(fmd_adm_t * ap,const char * fmri)5980Sstevel@tonic-gate fmd_adm_rsrc_flush(fmd_adm_t *ap, const char *fmri)
5990Sstevel@tonic-gate {
6000Sstevel@tonic-gate char *str = (char *)fmri;
6010Sstevel@tonic-gate int err;
6027238Seschrock enum clnt_stat cs;
6037238Seschrock uint_t retries = 0;
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate if (fmri == NULL)
6060Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
6070Sstevel@tonic-gate
6087238Seschrock do {
6097238Seschrock cs = fmd_adm_rsrcflush_1(str, &err, ap->adm_clnt);
6107238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
6117238Seschrock
6127238Seschrock if (cs != RPC_SUCCESS)
6130Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate int
fmd_adm_rsrc_repaired(fmd_adm_t * ap,const char * fmri)6197275Sstephh fmd_adm_rsrc_repaired(fmd_adm_t *ap, const char *fmri)
6200Sstevel@tonic-gate {
6210Sstevel@tonic-gate char *str = (char *)fmri;
6220Sstevel@tonic-gate int err;
6237238Seschrock enum clnt_stat cs;
6247238Seschrock uint_t retries = 0;
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate if (fmri == NULL)
6270Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
6280Sstevel@tonic-gate
6297238Seschrock do {
6307275Sstephh cs = fmd_adm_rsrcrepaired_1(str, &err, ap->adm_clnt);
6317275Sstephh } while (fmd_adm_retry(ap, cs, &retries));
6327275Sstephh
6337275Sstephh if (cs != RPC_SUCCESS)
6347275Sstephh return (fmd_adm_set_errno(ap, EPROTO));
6357275Sstephh
6367275Sstephh return (fmd_adm_set_svcerr(ap, err));
6377275Sstephh }
6387275Sstephh
6397275Sstephh int
fmd_adm_rsrc_replaced(fmd_adm_t * ap,const char * fmri)6407275Sstephh fmd_adm_rsrc_replaced(fmd_adm_t *ap, const char *fmri)
6417275Sstephh {
6427275Sstephh char *str = (char *)fmri;
6437275Sstephh int err;
6447275Sstephh enum clnt_stat cs;
6457275Sstephh uint_t retries = 0;
6467275Sstephh
6477275Sstephh if (fmri == NULL)
6487275Sstephh return (fmd_adm_set_errno(ap, EINVAL));
6497275Sstephh
6507275Sstephh do {
6517275Sstephh cs = fmd_adm_rsrcreplaced_1(str, &err, ap->adm_clnt);
6527275Sstephh } while (fmd_adm_retry(ap, cs, &retries));
6537275Sstephh
6547275Sstephh if (cs != RPC_SUCCESS)
6557275Sstephh return (fmd_adm_set_errno(ap, EPROTO));
6567275Sstephh
6577275Sstephh return (fmd_adm_set_svcerr(ap, err));
6587275Sstephh }
6597275Sstephh
6607275Sstephh int
fmd_adm_rsrc_acquit(fmd_adm_t * ap,const char * fmri,const char * uuid)6617275Sstephh fmd_adm_rsrc_acquit(fmd_adm_t *ap, const char *fmri, const char *uuid)
6627275Sstephh {
6637275Sstephh char *str = (char *)fmri;
6647275Sstephh char *str2 = (char *)uuid;
6657275Sstephh int err;
6667275Sstephh enum clnt_stat cs;
6677275Sstephh uint_t retries = 0;
6687275Sstephh
6697275Sstephh if (fmri == NULL)
6707275Sstephh return (fmd_adm_set_errno(ap, EINVAL));
6717275Sstephh
6727275Sstephh do {
6737275Sstephh cs = fmd_adm_rsrcacquit_1(str, str2, &err, ap->adm_clnt);
6747238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
6757238Seschrock
6767238Seschrock if (cs != RPC_SUCCESS)
6770Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate int
fmd_adm_case_repair(fmd_adm_t * ap,const char * uuid)6830Sstevel@tonic-gate fmd_adm_case_repair(fmd_adm_t *ap, const char *uuid)
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate char *str = (char *)uuid;
6860Sstevel@tonic-gate int err;
6877238Seschrock enum clnt_stat cs;
6887238Seschrock uint_t retries = 0;
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate if (uuid == NULL)
6910Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
6920Sstevel@tonic-gate
6937238Seschrock do {
6947238Seschrock cs = fmd_adm_caserepair_1(str, &err, ap->adm_clnt);
6957238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
6967238Seschrock
6977238Seschrock if (cs != RPC_SUCCESS)
6980Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate
7037275Sstephh int
fmd_adm_case_acquit(fmd_adm_t * ap,const char * uuid)7047275Sstephh fmd_adm_case_acquit(fmd_adm_t *ap, const char *uuid)
7057275Sstephh {
7067275Sstephh char *str = (char *)uuid;
7077275Sstephh int err;
7087275Sstephh enum clnt_stat cs;
7097275Sstephh uint_t retries = 0;
7107275Sstephh
7117275Sstephh if (uuid == NULL)
7127275Sstephh return (fmd_adm_set_errno(ap, EINVAL));
7137275Sstephh
7147275Sstephh do {
7157275Sstephh cs = fmd_adm_caseacquit_1(str, &err, ap->adm_clnt);
7167275Sstephh } while (fmd_adm_retry(ap, cs, &retries));
7177275Sstephh
7187275Sstephh if (cs != RPC_SUCCESS)
7197275Sstephh return (fmd_adm_set_errno(ap, EPROTO));
7207275Sstephh
7217275Sstephh return (fmd_adm_set_svcerr(ap, err));
7227275Sstephh }
7237275Sstephh
7240Sstevel@tonic-gate static int
fmd_adm_case_cmp(const void * lp,const void * rp)7251303Swesolows fmd_adm_case_cmp(const void *lp, const void *rp)
7261303Swesolows {
7271303Swesolows return (strcmp(*(char **)lp, *(char **)rp));
7281303Swesolows }
7291303Swesolows
7301303Swesolows static int
fmd_adm_case_one(fmd_adm_caseinfo_t * acp,const char * url_token,fmd_adm_case_f * func,void * arg)7311303Swesolows fmd_adm_case_one(fmd_adm_caseinfo_t *acp, const char *url_token,
7321303Swesolows fmd_adm_case_f *func, void *arg)
7331303Swesolows {
7341303Swesolows char *p, *urlcode, *dict, *olang;
7351303Swesolows const char *url;
7361303Swesolows size_t len;
7371303Swesolows
7381303Swesolows if ((p = strchr(acp->aci_code, '-')) == NULL ||
7391303Swesolows p == acp->aci_code) {
7401303Swesolows acp->aci_url = NULL;
7411303Swesolows } else {
7421303Swesolows dict = alloca((size_t)(p - acp->aci_code) + 1);
7431303Swesolows (void) strncpy(dict, acp->aci_code,
7441303Swesolows (size_t)(p - acp->aci_code));
7451303Swesolows dict[(size_t)(p - acp->aci_code)] = '\0';
7461303Swesolows
7471303Swesolows /*
7481303Swesolows * If we're given a token to use in looking up the URL, try
7491303Swesolows * to use it. Otherwise, or if we don't find it that way,
7501303Swesolows * use the fallback.
7511303Swesolows */
7521303Swesolows if (url_token == NULL) {
7531303Swesolows url = _url_fallback;
7541303Swesolows } else if ((url = dgettext(dict, url_token)) == url_token) {
7551303Swesolows /*
7561303Swesolows * We didn't find a translation in the
7571303Swesolows * dictionary for the current language. Fall
7581303Swesolows * back to C and try again.
7591303Swesolows */
7601303Swesolows olang = setlocale(LC_MESSAGES, NULL);
7611303Swesolows (void) setlocale(LC_MESSAGES, "C");
7621303Swesolows if ((url = dgettext(dict, url_token)) == url_token)
7631303Swesolows url = _url_fallback;
7641303Swesolows (void) setlocale(LC_MESSAGES, olang);
7651303Swesolows }
7661303Swesolows len = strlen(url);
7671303Swesolows if (url[len - 1] == '/') {
7681303Swesolows len += strlen(acp->aci_code) + 1;
7691303Swesolows urlcode = alloca(len);
7701303Swesolows (void) snprintf(urlcode, len, "%s%s", url,
7711303Swesolows acp->aci_code);
7721303Swesolows } else {
7731303Swesolows urlcode = (char *)url;
7741303Swesolows }
7751303Swesolows acp->aci_url = urlcode;
7761303Swesolows }
7771303Swesolows
7781303Swesolows return (func(acp, arg));
7791303Swesolows }
7801303Swesolows
7811303Swesolows /*
7821303Swesolows * Our approach to cases is the same as for resources: we first obtain a
7831303Swesolows * list of UUIDs, sort them, then obtain the case information for each.
7841303Swesolows */
7851303Swesolows int
fmd_adm_case_iter(fmd_adm_t * ap,const char * url_token,fmd_adm_case_f * func,void * arg)7861303Swesolows fmd_adm_case_iter(fmd_adm_t *ap, const char *url_token, fmd_adm_case_f *func,
7871303Swesolows void *arg)
7881303Swesolows {
7891303Swesolows struct fmd_rpc_caselist rcl;
7901303Swesolows struct fmd_rpc_caseinfo rci;
7911303Swesolows fmd_adm_caseinfo_t aci;
7921303Swesolows char **uuids, *p;
7931303Swesolows int i, rv;
7947238Seschrock enum clnt_stat cs;
7957238Seschrock uint_t retries = 0;
7961303Swesolows
7971303Swesolows bzero(&rcl, sizeof (rcl)); /* tell xdr to allocate memory for us */
7981303Swesolows
7997238Seschrock do {
8007238Seschrock cs = fmd_adm_caselist_1(&rcl, ap->adm_clnt);
8017238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
8027238Seschrock
8037238Seschrock if (cs != RPC_SUCCESS)
8041303Swesolows return (fmd_adm_set_errno(ap, EPROTO));
8051303Swesolows
8061303Swesolows if (rcl.rcl_err != 0) {
8071303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8081303Swesolows return (fmd_adm_set_svcerr(ap, rcl.rcl_err));
8091303Swesolows }
8101303Swesolows
8111303Swesolows if ((uuids = malloc(sizeof (char *) * rcl.rcl_cnt)) == NULL) {
8121303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8131303Swesolows return (fmd_adm_set_errno(ap, EAGAIN));
8141303Swesolows }
8151303Swesolows
8161303Swesolows p = rcl.rcl_buf.rcl_buf_val;
8171303Swesolows
8181303Swesolows for (i = 0; i < rcl.rcl_cnt; i++, p += strlen(p) + 1)
8191303Swesolows uuids[i] = p;
8201303Swesolows
8211303Swesolows qsort(uuids, rcl.rcl_cnt, sizeof (char *), fmd_adm_case_cmp);
8221303Swesolows
8231303Swesolows for (i = 0; i < rcl.rcl_cnt; i++) {
8241303Swesolows bzero(&rci, sizeof (rci));
8251303Swesolows
8267238Seschrock retries = 0;
8277238Seschrock do {
8287238Seschrock cs = fmd_adm_caseinfo_1(uuids[i], &rci, ap->adm_clnt);
8297238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
8307238Seschrock
8317238Seschrock if (cs != RPC_SUCCESS) {
8321303Swesolows free(uuids);
8331303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8341303Swesolows return (fmd_adm_set_errno(ap, EPROTO));
8351303Swesolows }
8361303Swesolows
8371303Swesolows if (rci.rci_err != 0 && rci.rci_err != FMD_ADM_ERR_CASESRCH) {
8381303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8391303Swesolows free(uuids);
8401303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8411303Swesolows return (fmd_adm_set_svcerr(ap, rci.rci_err));
8421303Swesolows }
8431303Swesolows
8441303Swesolows if (rci.rci_err == FMD_ADM_ERR_CASESRCH) {
8451303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8461303Swesolows continue;
8471303Swesolows }
8481303Swesolows
8491303Swesolows bzero(&aci, sizeof (aci));
8501303Swesolows
8511303Swesolows if ((rv = nvlist_unpack(rci.rci_evbuf.rci_evbuf_val,
8521303Swesolows rci.rci_evbuf.rci_evbuf_len, &aci.aci_event, 0)) != 0) {
8531303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8541303Swesolows free(uuids);
8551303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8561303Swesolows return (fmd_adm_set_errno(ap, rv));
8571303Swesolows }
8581303Swesolows
8591303Swesolows if ((rv = nvlist_lookup_string(aci.aci_event, FM_SUSPECT_UUID,
8601303Swesolows (char **)&aci.aci_uuid)) != 0) {
8611303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8621303Swesolows free(uuids);
8631303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8641303Swesolows nvlist_free(aci.aci_event);
8651303Swesolows return (fmd_adm_set_errno(ap, rv));
8661303Swesolows }
8671303Swesolows if ((rv = nvlist_lookup_string(aci.aci_event,
8681303Swesolows FM_SUSPECT_DIAG_CODE, (char **)&aci.aci_code)) != 0) {
8691303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8701303Swesolows free(uuids);
8711303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8721303Swesolows nvlist_free(aci.aci_event);
8731303Swesolows return (fmd_adm_set_errno(ap, rv));
8741303Swesolows }
8751303Swesolows
8761303Swesolows rv = fmd_adm_case_one(&aci, url_token, func, arg);
8771303Swesolows
8781303Swesolows xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
8791303Swesolows nvlist_free(aci.aci_event);
8801303Swesolows
8811303Swesolows if (rv != 0)
8821303Swesolows break;
8831303Swesolows }
8841303Swesolows
8851303Swesolows free(uuids);
8861303Swesolows xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
8871303Swesolows return (0);
8881303Swesolows }
8891303Swesolows
8901303Swesolows static int
fmd_adm_serd_cmp(const void * lp,const void * rp)8910Sstevel@tonic-gate fmd_adm_serd_cmp(const void *lp, const void *rp)
8920Sstevel@tonic-gate {
893*11400SJakub.Jermar@Sun.COM return (strcmp(*(char **)lp, *(char **)rp));
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate int
fmd_adm_serd_iter(fmd_adm_t * ap,const char * name,fmd_adm_serd_f * func,void * arg)8970Sstevel@tonic-gate fmd_adm_serd_iter(fmd_adm_t *ap, const char *name,
8980Sstevel@tonic-gate fmd_adm_serd_f *func, void *arg)
8990Sstevel@tonic-gate {
9000Sstevel@tonic-gate struct fmd_rpc_serdlist rsl;
901*11400SJakub.Jermar@Sun.COM struct fmd_rpc_serdinfo rsi;
902*11400SJakub.Jermar@Sun.COM char **serds, *p;
9030Sstevel@tonic-gate fmd_adm_serdinfo_t asi;
9047238Seschrock enum clnt_stat cs;
9057238Seschrock uint_t retries = 0;
906*11400SJakub.Jermar@Sun.COM int i, rv;
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate bzero(&rsl, sizeof (rsl)); /* tell xdr to allocate memory for us */
9090Sstevel@tonic-gate
9107238Seschrock do {
911*11400SJakub.Jermar@Sun.COM cs = fmd_adm_serdlist_1((char *)name, &rsl, ap->adm_clnt);
9127238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
9137238Seschrock
9147238Seschrock if (cs != RPC_SUCCESS)
9150Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate if (rsl.rsl_err != 0 || rsl.rsl_len == 0) {
9180Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9190Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, rsl.rsl_err));
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate
922*11400SJakub.Jermar@Sun.COM if ((serds = malloc(sizeof (char *) * rsl.rsl_cnt)) == NULL) {
9230Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9240Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EAGAIN));
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate
927*11400SJakub.Jermar@Sun.COM p = rsl.rsl_buf.rsl_buf_val;
928*11400SJakub.Jermar@Sun.COM
929*11400SJakub.Jermar@Sun.COM for (i = 0; i < rsl.rsl_cnt; i++, p += strlen(p) + 1)
930*11400SJakub.Jermar@Sun.COM serds[i] = p;
931*11400SJakub.Jermar@Sun.COM
932*11400SJakub.Jermar@Sun.COM qsort(serds, rsl.rsl_cnt, sizeof (char *), fmd_adm_serd_cmp);
9330Sstevel@tonic-gate
934*11400SJakub.Jermar@Sun.COM for (i = 0; i < rsl.rsl_cnt; i++) {
935*11400SJakub.Jermar@Sun.COM bzero(&rsi, sizeof (rsi));
936*11400SJakub.Jermar@Sun.COM
937*11400SJakub.Jermar@Sun.COM retries = 0;
938*11400SJakub.Jermar@Sun.COM do {
939*11400SJakub.Jermar@Sun.COM cs = fmd_adm_serdinfo_1((char *)name, serds[i], &rsi,
940*11400SJakub.Jermar@Sun.COM ap->adm_clnt);
941*11400SJakub.Jermar@Sun.COM } while (fmd_adm_retry(ap, cs, &retries));
9420Sstevel@tonic-gate
943*11400SJakub.Jermar@Sun.COM if (cs != RPC_SUCCESS) {
944*11400SJakub.Jermar@Sun.COM free(serds);
945*11400SJakub.Jermar@Sun.COM xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
946*11400SJakub.Jermar@Sun.COM return (fmd_adm_set_errno(ap, EPROTO));
947*11400SJakub.Jermar@Sun.COM }
948*11400SJakub.Jermar@Sun.COM
949*11400SJakub.Jermar@Sun.COM if (rsi.rsi_err != 0 && rsi.rsi_err != FMD_ADM_ERR_SERDSRCH) {
950*11400SJakub.Jermar@Sun.COM free(serds);
951*11400SJakub.Jermar@Sun.COM xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
952*11400SJakub.Jermar@Sun.COM xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
953*11400SJakub.Jermar@Sun.COM return (fmd_adm_set_svcerr(ap, rsi.rsi_err));
954*11400SJakub.Jermar@Sun.COM }
9550Sstevel@tonic-gate
956*11400SJakub.Jermar@Sun.COM if (rsi.rsi_err == FMD_ADM_ERR_SERDSRCH) {
957*11400SJakub.Jermar@Sun.COM xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
958*11400SJakub.Jermar@Sun.COM continue;
959*11400SJakub.Jermar@Sun.COM }
960*11400SJakub.Jermar@Sun.COM
961*11400SJakub.Jermar@Sun.COM bzero(&asi, sizeof (asi));
962*11400SJakub.Jermar@Sun.COM
963*11400SJakub.Jermar@Sun.COM asi.asi_name = rsi.rsi_name;
964*11400SJakub.Jermar@Sun.COM asi.asi_delta = rsi.rsi_delta;
965*11400SJakub.Jermar@Sun.COM asi.asi_n = rsi.rsi_n;
966*11400SJakub.Jermar@Sun.COM asi.asi_t = rsi.rsi_t;
967*11400SJakub.Jermar@Sun.COM asi.asi_count = rsi.rsi_count;
9680Sstevel@tonic-gate asi.asi_flags = 0;
9690Sstevel@tonic-gate
970*11400SJakub.Jermar@Sun.COM if (rsi.rsi_fired)
9710Sstevel@tonic-gate asi.asi_flags |= FMD_ADM_SERD_FIRED;
9720Sstevel@tonic-gate
973*11400SJakub.Jermar@Sun.COM rv = func(&asi, arg);
974*11400SJakub.Jermar@Sun.COM
975*11400SJakub.Jermar@Sun.COM xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
976*11400SJakub.Jermar@Sun.COM
977*11400SJakub.Jermar@Sun.COM if (rv != 0)
9780Sstevel@tonic-gate break;
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
981*11400SJakub.Jermar@Sun.COM free(serds);
9820Sstevel@tonic-gate xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9830Sstevel@tonic-gate return (0);
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate int
fmd_adm_serd_reset(fmd_adm_t * ap,const char * mod,const char * name)9870Sstevel@tonic-gate fmd_adm_serd_reset(fmd_adm_t *ap, const char *mod, const char *name)
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate char *s1 = (char *)mod, *s2 = (char *)name;
9900Sstevel@tonic-gate int err;
9917238Seschrock enum clnt_stat cs;
9927238Seschrock uint_t retries = 0;
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate if (mod == NULL || name == NULL || strchr(mod, '/') != NULL)
9950Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
9960Sstevel@tonic-gate
9977238Seschrock do {
9987238Seschrock cs = fmd_adm_serdreset_1(s1, s2, &err, ap->adm_clnt);
9997238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
10007238Seschrock
10017238Seschrock if (cs != RPC_SUCCESS)
10020Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate int
fmd_adm_xprt_iter(fmd_adm_t * ap,fmd_adm_xprt_f * func,void * arg)10081193Smws fmd_adm_xprt_iter(fmd_adm_t *ap, fmd_adm_xprt_f *func, void *arg)
10091193Smws {
10101193Smws struct fmd_rpc_xprtlist rxl;
10111193Smws uint_t i;
10127238Seschrock enum clnt_stat cs;
10137238Seschrock uint_t retries = 0;
10141193Smws
10151193Smws bzero(&rxl, sizeof (rxl)); /* tell xdr to allocate memory for us */
10161193Smws
10177238Seschrock do {
10187238Seschrock cs = fmd_adm_xprtlist_1(&rxl, ap->adm_clnt);
10197238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
10207238Seschrock
10217238Seschrock if (cs != RPC_SUCCESS)
10221193Smws return (fmd_adm_set_errno(ap, EPROTO));
10231193Smws
10241193Smws if (rxl.rxl_err != 0) {
10251193Smws xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl);
10261193Smws return (fmd_adm_set_svcerr(ap, rxl.rxl_err));
10271193Smws }
10281193Smws
10291193Smws for (i = 0; i < rxl.rxl_len; i++)
10301193Smws func(rxl.rxl_buf.rxl_buf_val[i], arg);
10311193Smws
10321193Smws xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl);
10331193Smws return (0);
10341193Smws }
10351193Smws
10361193Smws int
fmd_adm_xprt_stats(fmd_adm_t * ap,id_t id,fmd_adm_stats_t * sp)10371193Smws fmd_adm_xprt_stats(fmd_adm_t *ap, id_t id, fmd_adm_stats_t *sp)
10381193Smws {
10391193Smws struct fmd_rpc_modstat rms;
10407238Seschrock enum clnt_stat cs;
10417238Seschrock uint_t retries = 0;
10421193Smws
10431193Smws if (sp == NULL)
10441193Smws return (fmd_adm_set_errno(ap, EINVAL));
10451193Smws
10461193Smws bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
10471193Smws
10487238Seschrock do {
10497238Seschrock cs = fmd_adm_xprtstat_1(id, &rms, ap->adm_clnt);
10507238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
10517238Seschrock
10527238Seschrock if (cs != RPC_SUCCESS)
10531193Smws return (fmd_adm_set_errno(ap, EPROTO));
10541193Smws
10551193Smws if (rms.rms_err != 0) {
10561193Smws xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
10571193Smws return (fmd_adm_set_svcerr(ap, rms.rms_err));
10581193Smws }
10591193Smws
10601193Smws sp->ams_buf = rms.rms_buf.rms_buf_val;
10611193Smws sp->ams_len = rms.rms_buf.rms_buf_len;
10621193Smws
10631193Smws return (0);
10641193Smws }
10651193Smws
10661193Smws int
fmd_adm_log_rotate(fmd_adm_t * ap,const char * log)10670Sstevel@tonic-gate fmd_adm_log_rotate(fmd_adm_t *ap, const char *log)
10680Sstevel@tonic-gate {
10690Sstevel@tonic-gate int err;
10707238Seschrock enum clnt_stat cs;
10717238Seschrock uint_t retries = 0;
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate if (log == NULL)
10740Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EINVAL));
10750Sstevel@tonic-gate
10767238Seschrock do {
10777238Seschrock cs = fmd_adm_logrotate_1((char *)log, &err, ap->adm_clnt);
10787238Seschrock } while (fmd_adm_retry(ap, cs, &retries));
10797238Seschrock
10807238Seschrock if (cs != RPC_SUCCESS)
10810Sstevel@tonic-gate return (fmd_adm_set_errno(ap, EPROTO));
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate return (fmd_adm_set_svcerr(ap, err));
10840Sstevel@tonic-gate }
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate /*
10870Sstevel@tonic-gate * Custom XDR routine for our API structure fmd_stat_t. This function must
10880Sstevel@tonic-gate * match the definition of fmd_stat_t in <fm/fmd_api.h> and must also match
10890Sstevel@tonic-gate * the corresponding routine in usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c.
10900Sstevel@tonic-gate */
10910Sstevel@tonic-gate bool_t
xdr_fmd_stat(XDR * xp,fmd_stat_t * sp)10920Sstevel@tonic-gate xdr_fmd_stat(XDR *xp, fmd_stat_t *sp)
10930Sstevel@tonic-gate {
10940Sstevel@tonic-gate bool_t rv = TRUE;
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name));
10970Sstevel@tonic-gate rv &= xdr_u_int(xp, &sp->fmds_type);
10980Sstevel@tonic-gate rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc));
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate switch (sp->fmds_type) {
11010Sstevel@tonic-gate case FMD_TYPE_BOOL:
11020Sstevel@tonic-gate rv &= xdr_int(xp, &sp->fmds_value.bool);
11030Sstevel@tonic-gate break;
11040Sstevel@tonic-gate case FMD_TYPE_INT32:
11050Sstevel@tonic-gate rv &= xdr_int32_t(xp, &sp->fmds_value.i32);
11060Sstevel@tonic-gate break;
11070Sstevel@tonic-gate case FMD_TYPE_UINT32:
11080Sstevel@tonic-gate rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32);
11090Sstevel@tonic-gate break;
11100Sstevel@tonic-gate case FMD_TYPE_INT64:
11110Sstevel@tonic-gate rv &= xdr_int64_t(xp, &sp->fmds_value.i64);
11120Sstevel@tonic-gate break;
11130Sstevel@tonic-gate case FMD_TYPE_UINT64:
11140Sstevel@tonic-gate case FMD_TYPE_TIME:
11150Sstevel@tonic-gate case FMD_TYPE_SIZE:
11160Sstevel@tonic-gate rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64);
11170Sstevel@tonic-gate break;
11180Sstevel@tonic-gate case FMD_TYPE_STRING:
11190Sstevel@tonic-gate rv &= xdr_string(xp, &sp->fmds_value.str, ~0);
11200Sstevel@tonic-gate break;
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate return (rv);
11240Sstevel@tonic-gate }
1125