4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include <uuid/uuid.h>
35 #include <sys/fm/protocol.h>
36 #include <fmd_adm_impl.h>
37 #include <fmd_rpc_adm.h>
39 static const uint_t _fmd_adm_bufsize
= 128 * 1024;
40 static const char _url_fallback
[] = "http://illumos.org/msg/";
43 fmd_adm_open(const char *host
, uint32_t prog
, int version
)
49 if (version
!= FMD_ADM_VERSION
) {
57 if (prog
== FMD_ADM_PROGRAM
)
60 if ((ap
= malloc(sizeof (fmd_adm_t
))) == NULL
)
63 if (strcmp(host
, HOST_SELF
) == 0) {
64 c
= clnt_door_create(prog
, FMD_ADM_VERSION_1
, _fmd_adm_bufsize
);
65 ap
->adm_maxretries
= 1;
67 c
= clnt_create_vers(host
, prog
, &v
,
68 FMD_ADM_VERSION_1
, FMD_ADM_VERSION_1
, NULL
);
69 ap
->adm_maxretries
= 0;
80 ap
->adm_version
= version
;
88 fmd_adm_close(fmd_adm_t
*ap
)
91 return; /* permit NULL to simply caller code */
93 clnt_destroy(ap
->adm_clnt
);
98 fmd_adm_svc_errmsg(enum fmd_adm_error err
)
101 case FMD_ADM_ERR_NOMEM
:
102 return ("unable to perform request due to allocation failure");
103 case FMD_ADM_ERR_PERM
:
104 return ("operation requires additional privilege");
105 case FMD_ADM_ERR_MODSRCH
:
106 return ("specified module is not loaded in fault manager");
107 case FMD_ADM_ERR_MODBUSY
:
108 return ("module is in use and cannot be unloaded");
109 case FMD_ADM_ERR_MODFAIL
:
110 return ("module failed and can no longer export statistics");
111 case FMD_ADM_ERR_MODNOENT
:
112 return ("file missing or cannot be accessed by fault manager");
113 case FMD_ADM_ERR_MODEXIST
:
114 return ("module using same name is already loaded");
115 case FMD_ADM_ERR_MODINIT
:
116 return ("module failed to initialize (consult fmd(1M) log)");
117 case FMD_ADM_ERR_MODLOAD
:
118 return ("module failed to load (consult fmd(1M) log)");
119 case FMD_ADM_ERR_RSRCSRCH
:
120 return ("specified resource is not cached by fault manager");
121 case FMD_ADM_ERR_RSRCNOTF
:
122 return ("specified resource is not known to be faulty");
123 case FMD_ADM_ERR_SERDSRCH
:
124 return ("specified serd engine not present in module");
125 case FMD_ADM_ERR_SERDFIRED
:
126 return ("specified serd engine has already fired");
127 case FMD_ADM_ERR_ROTSRCH
:
128 return ("invalid log file name");
129 case FMD_ADM_ERR_ROTFAIL
:
130 return ("failed to rotate log file (consult fmd(1M) log)");
131 case FMD_ADM_ERR_ROTBUSY
:
132 return ("log file is too busy to rotate (try again later)");
133 case FMD_ADM_ERR_CASESRCH
:
134 return ("specified UUID is invalid or has been repaired");
135 case FMD_ADM_ERR_CASEOPEN
:
136 return ("specified UUID is still being diagnosed");
137 case FMD_ADM_ERR_XPRTSRCH
:
138 return ("specified transport ID is invalid or has been closed");
139 case FMD_ADM_ERR_CASEXPRT
:
140 return ("specified UUID is owned by a different fault manager");
141 case FMD_ADM_ERR_RSRCNOTR
:
142 return ("specified resource has not been replaced");
144 return ("unknown fault manager error");
149 fmd_adm_errmsg(fmd_adm_t
*ap
)
154 return ("client requires newer libfmd_adm version");
156 return (clnt_spcreateerror("failed to connect to fmd"));
160 switch (ap
? ap
->adm_errno
: errno
) {
162 return (clnt_sperror(ap
->adm_clnt
, "rpc call failed"));
164 return (fmd_adm_svc_errmsg(ap
->adm_svcerr
));
166 return (strerror(ap
->adm_errno
));
171 fmd_adm_set_svcerr(fmd_adm_t
*ap
, enum fmd_adm_error err
)
174 ap
->adm_svcerr
= err
;
175 ap
->adm_errno
= EREMOTE
;
178 ap
->adm_svcerr
= err
;
185 fmd_adm_set_errno(fmd_adm_t
*ap
, int err
)
193 fmd_adm_stats_cmp(const void *lp
, const void *rp
)
195 return (strcmp(((fmd_stat_t
*)lp
)->fmds_name
,
196 ((fmd_stat_t
*)rp
)->fmds_name
));
200 * If the server (fmd) is restarted, this will cause all future door calls to
201 * fail. Unfortunately, once the server comes back up, we have no way of
202 * reestablishing the connection. To get around this, if the error indicates
203 * that the RPC call failed, we reopen the client handle and try again. For
204 * simplicity we only deal with the door case, as it's unclear whether the
205 * remote case suffers from the same pathology.
208 fmd_adm_retry(fmd_adm_t
*ap
, enum clnt_stat cs
, uint_t
*retries
)
213 if (cs
== RPC_SUCCESS
|| *retries
== ap
->adm_maxretries
)
216 clnt_geterr(ap
->adm_clnt
, &err
);
217 if (err
.re_status
!= RPC_CANTSEND
)
220 if ((c
= clnt_door_create(ap
->adm_prog
, FMD_ADM_VERSION_1
,
221 _fmd_adm_bufsize
)) == NULL
)
226 clnt_destroy(ap
->adm_clnt
);
233 fmd_adm_stats_read(fmd_adm_t
*ap
, const char *name
, fmd_adm_stats_t
*sp
)
235 struct fmd_rpc_modstat rms
;
240 return (fmd_adm_set_errno(ap
, EINVAL
));
242 bzero(&rms
, sizeof (rms
)); /* tell xdr to allocate memory for us */
246 cs
= fmd_adm_modcstat_1((char *)name
, &rms
,
249 cs
= fmd_adm_modgstat_1(&rms
, ap
->adm_clnt
);
250 } while (fmd_adm_retry(ap
, cs
, &retries
));
252 if (cs
!= RPC_SUCCESS
)
253 return (fmd_adm_set_errno(ap
, EPROTO
));
255 if (rms
.rms_err
!= 0) {
256 xdr_free(xdr_fmd_rpc_modstat
, (char *)&rms
);
257 return (fmd_adm_set_svcerr(ap
, rms
.rms_err
));
260 sp
->ams_buf
= rms
.rms_buf
.rms_buf_val
;
261 sp
->ams_len
= rms
.rms_buf
.rms_buf_len
;
263 if (sp
->ams_len
!= 0) {
264 qsort(sp
->ams_buf
, sp
->ams_len
,
265 sizeof (fmd_stat_t
), fmd_adm_stats_cmp
);
272 fmd_adm_stats_free(fmd_adm_t
*ap
, fmd_adm_stats_t
*sp
)
274 struct fmd_rpc_modstat rms
;
277 return (fmd_adm_set_errno(ap
, EINVAL
));
279 rms
.rms_buf
.rms_buf_val
= sp
->ams_buf
;
280 rms
.rms_buf
.rms_buf_len
= sp
->ams_len
;
283 xdr_free(xdr_fmd_rpc_modstat
, (char *)&rms
);
284 bzero(sp
, sizeof (fmd_adm_stats_t
));
290 fmd_adm_module_cmp(const void *lp
, const void *rp
)
292 return (strcmp((*(struct fmd_rpc_modinfo
**)lp
)->rmi_name
,
293 (*(struct fmd_rpc_modinfo
**)rp
)->rmi_name
));
297 fmd_adm_module_iter(fmd_adm_t
*ap
, fmd_adm_module_f
*func
, void *arg
)
299 struct fmd_rpc_modinfo
*rmi
, **rms
, **rmp
;
300 struct fmd_rpc_modlist rml
;
301 fmd_adm_modinfo_t ami
;
305 bzero(&rml
, sizeof (rml
)); /* tell xdr to allocate memory for us */
308 cs
= fmd_adm_modinfo_1(&rml
, ap
->adm_clnt
);
309 } while (fmd_adm_retry(ap
, cs
, &retries
));
311 if (cs
!= RPC_SUCCESS
)
312 return (fmd_adm_set_errno(ap
, EPROTO
));
314 if (rml
.rml_err
!= 0 || rml
.rml_len
== 0) {
315 xdr_free(xdr_fmd_rpc_modlist
, (char *)&rml
);
316 return (fmd_adm_set_svcerr(ap
, rml
.rml_err
));
319 if ((rms
= rmp
= malloc(sizeof (void *) * rml
.rml_len
)) == NULL
) {
320 xdr_free(xdr_fmd_rpc_modlist
, (char *)&rml
);
321 return (fmd_adm_set_errno(ap
, EAGAIN
));
324 for (rmi
= rml
.rml_list
; rmi
!= NULL
; rmi
= rmi
->rmi_next
)
325 *rmp
++ = rmi
; /* store copy of pointer in array for sorting */
327 qsort(rms
, rml
.rml_len
, sizeof (void *), fmd_adm_module_cmp
);
329 for (rmp
= rms
; rmp
< rms
+ rml
.rml_len
; rmp
++) {
332 ami
.ami_name
= rmi
->rmi_name
;
333 ami
.ami_desc
= rmi
->rmi_desc
;
334 ami
.ami_vers
= rmi
->rmi_vers
;
338 ami
.ami_flags
|= FMD_ADM_MOD_FAILED
;
340 if (func(&ami
, arg
) != 0)
345 xdr_free(xdr_fmd_rpc_modlist
, (char *)&rml
);
350 fmd_adm_module_load(fmd_adm_t
*ap
, const char *path
)
352 char *str
= (char *)path
;
357 if (path
== NULL
|| path
[0] != '/')
358 return (fmd_adm_set_errno(ap
, EINVAL
));
361 cs
= fmd_adm_modload_1(str
, &err
, ap
->adm_clnt
);
362 } while (fmd_adm_retry(ap
, cs
, &retries
));
364 if (cs
!= RPC_SUCCESS
)
365 return (fmd_adm_set_errno(ap
, EPROTO
));
367 return (fmd_adm_set_svcerr(ap
, err
));
371 fmd_adm_module_unload(fmd_adm_t
*ap
, const char *name
)
373 char *str
= (char *)name
;
378 if (name
== NULL
|| strchr(name
, '/') != NULL
)
379 return (fmd_adm_set_errno(ap
, EINVAL
));
382 cs
= fmd_adm_modunload_1(str
, &err
, ap
->adm_clnt
);
383 } while (fmd_adm_retry(ap
, cs
, &retries
));
385 if (cs
!= RPC_SUCCESS
)
386 return (fmd_adm_set_errno(ap
, EPROTO
));
388 return (fmd_adm_set_svcerr(ap
, err
));
392 fmd_adm_module_reset(fmd_adm_t
*ap
, const char *name
)
394 char *str
= (char *)name
;
399 if (name
== NULL
|| strchr(name
, '/') != NULL
)
400 return (fmd_adm_set_errno(ap
, EINVAL
));
403 cs
= fmd_adm_modreset_1(str
, &err
, ap
->adm_clnt
);
404 } while (fmd_adm_retry(ap
, cs
, &retries
));
406 if (cs
!= RPC_SUCCESS
)
407 return (fmd_adm_set_errno(ap
, EPROTO
));
409 return (fmd_adm_set_svcerr(ap
, err
));
413 fmd_adm_module_gc(fmd_adm_t
*ap
, const char *name
)
415 char *str
= (char *)name
;
420 if (name
== NULL
|| strchr(name
, '/') != NULL
)
421 return (fmd_adm_set_errno(ap
, EINVAL
));
424 cs
= fmd_adm_modgc_1(str
, &err
, ap
->adm_clnt
);
425 } while (fmd_adm_retry(ap
, cs
, &retries
));
427 if (cs
!= RPC_SUCCESS
)
428 return (fmd_adm_set_errno(ap
, EPROTO
));
430 return (fmd_adm_set_svcerr(ap
, err
));
434 fmd_adm_module_stats(fmd_adm_t
*ap
, const char *name
, fmd_adm_stats_t
*sp
)
436 struct fmd_rpc_modstat rms
;
440 if (name
== NULL
|| sp
== NULL
)
441 return (fmd_adm_set_errno(ap
, EINVAL
));
443 bzero(&rms
, sizeof (rms
)); /* tell xdr to allocate memory for us */
446 cs
= fmd_adm_moddstat_1((char *)name
, &rms
, ap
->adm_clnt
);
447 } while (fmd_adm_retry(ap
, cs
, &retries
));
449 if (cs
!= RPC_SUCCESS
)
450 return (fmd_adm_set_errno(ap
, EPROTO
));
452 if (rms
.rms_err
!= 0) {
453 xdr_free(xdr_fmd_rpc_modstat
, (char *)&rms
);
454 return (fmd_adm_set_svcerr(ap
, rms
.rms_err
));
457 sp
->ams_buf
= rms
.rms_buf
.rms_buf_val
;
458 sp
->ams_len
= rms
.rms_buf
.rms_buf_len
;
464 fmd_adm_rsrc_count(fmd_adm_t
*ap
, int all
, uint32_t *rcp
)
466 struct fmd_rpc_rsrclist rrl
;
471 return (fmd_adm_set_errno(ap
, EINVAL
));
473 bzero(&rrl
, sizeof (rrl
)); /* tell xdr to allocate memory for us */
476 cs
= fmd_adm_rsrclist_1(all
, &rrl
, ap
->adm_clnt
);
477 } while (fmd_adm_retry(ap
, cs
, &retries
));
479 if (cs
!= RPC_SUCCESS
)
480 return (fmd_adm_set_errno(ap
, EPROTO
));
482 if (rrl
.rrl_err
!= 0) {
483 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
484 return (fmd_adm_set_svcerr(ap
, rrl
.rrl_err
));
488 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
493 fmd_adm_rsrc_cmp(const void *lp
, const void *rp
)
495 return (strcmp(*(char **)lp
, *(char **)rp
));
499 fmd_adm_rsrc_iter(fmd_adm_t
*ap
, int all
, fmd_adm_rsrc_f
*func
, void *arg
)
501 struct fmd_rpc_rsrclist rrl
;
502 struct fmd_rpc_rsrcinfo rri
;
503 fmd_adm_rsrcinfo_t ari
;
509 bzero(&rrl
, sizeof (rrl
)); /* tell xdr to allocate memory for us */
512 cs
= fmd_adm_rsrclist_1(all
, &rrl
, ap
->adm_clnt
);
513 } while (fmd_adm_retry(ap
, cs
, &retries
));
515 if (cs
!= RPC_SUCCESS
)
516 return (fmd_adm_set_errno(ap
, EPROTO
));
518 if (rrl
.rrl_err
!= 0) {
519 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
520 return (fmd_adm_set_svcerr(ap
, rrl
.rrl_err
));
523 if ((fmris
= malloc(sizeof (char *) * rrl
.rrl_cnt
)) == NULL
) {
524 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
525 return (fmd_adm_set_errno(ap
, EAGAIN
));
529 * The fmd_adm_rsrclist_1 request returns an opaque XDR buffer that is
530 * a string table of FMRIs (e.g. "fmriA\0fmriB\0...") where rrl_cnt is
531 * the number of strings in the table and rrl_buf_val is its address.
532 * We construct an array of pointers into the string table and sort it.
534 p
= rrl
.rrl_buf
.rrl_buf_val
;
536 for (i
= 0; i
< rrl
.rrl_cnt
; i
++, p
+= strlen(p
) + 1)
537 fmris
[i
] = p
; /* store fmri pointer in array for sorting */
539 qsort(fmris
, rrl
.rrl_cnt
, sizeof (char *), fmd_adm_rsrc_cmp
);
542 * For each FMRI in the resource cache snapshot, use fmd_adm_rsrcinfo_1
543 * to get more information and the invoke the callback function. If
544 * FMD_ADM_ERR_RSRCSRCH is returned, the FMRI has been purged from the
545 * cache since our snapshot: this error is therefore silently ignored.
547 for (i
= 0; i
< rrl
.rrl_cnt
; i
++) {
548 bzero(&rri
, sizeof (rri
));
552 cs
= fmd_adm_rsrcinfo_1(fmris
[i
], &rri
, ap
->adm_clnt
);
553 } while (fmd_adm_retry(ap
, cs
, &retries
));
555 if (cs
!= RPC_SUCCESS
) {
557 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
558 return (fmd_adm_set_errno(ap
, EPROTO
));
561 if (rri
.rri_err
!= 0 && rri
.rri_err
!= FMD_ADM_ERR_RSRCSRCH
) {
562 xdr_free(xdr_fmd_rpc_rsrcinfo
, (char *)&rri
);
564 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
565 return (fmd_adm_set_svcerr(ap
, rri
.rri_err
));
568 if (rri
.rri_err
== FMD_ADM_ERR_RSRCSRCH
) {
569 xdr_free(xdr_fmd_rpc_rsrcinfo
, (char *)&rri
);
573 ari
.ari_fmri
= rri
.rri_fmri
;
574 ari
.ari_uuid
= rri
.rri_uuid
;
575 ari
.ari_case
= rri
.rri_case
;
579 ari
.ari_flags
|= FMD_ADM_RSRC_FAULTY
;
580 if (rri
.rri_unusable
)
581 ari
.ari_flags
|= FMD_ADM_RSRC_UNUSABLE
;
582 if (rri
.rri_invisible
)
583 ari
.ari_flags
|= FMD_ADM_RSRC_INVISIBLE
;
585 rv
= func(&ari
, arg
);
586 xdr_free(xdr_fmd_rpc_rsrcinfo
, (char *)&rri
);
593 xdr_free(xdr_fmd_rpc_rsrclist
, (char *)&rrl
);
598 fmd_adm_rsrc_flush(fmd_adm_t
*ap
, const char *fmri
)
600 char *str
= (char *)fmri
;
606 return (fmd_adm_set_errno(ap
, EINVAL
));
609 cs
= fmd_adm_rsrcflush_1(str
, &err
, ap
->adm_clnt
);
610 } while (fmd_adm_retry(ap
, cs
, &retries
));
612 if (cs
!= RPC_SUCCESS
)
613 return (fmd_adm_set_errno(ap
, EPROTO
));
615 return (fmd_adm_set_svcerr(ap
, err
));
619 fmd_adm_rsrc_repaired(fmd_adm_t
*ap
, const char *fmri
)
621 char *str
= (char *)fmri
;
627 return (fmd_adm_set_errno(ap
, EINVAL
));
630 cs
= fmd_adm_rsrcrepaired_1(str
, &err
, ap
->adm_clnt
);
631 } while (fmd_adm_retry(ap
, cs
, &retries
));
633 if (cs
!= RPC_SUCCESS
)
634 return (fmd_adm_set_errno(ap
, EPROTO
));
636 return (fmd_adm_set_svcerr(ap
, err
));
640 fmd_adm_rsrc_replaced(fmd_adm_t
*ap
, const char *fmri
)
642 char *str
= (char *)fmri
;
648 return (fmd_adm_set_errno(ap
, EINVAL
));
651 cs
= fmd_adm_rsrcreplaced_1(str
, &err
, ap
->adm_clnt
);
652 } while (fmd_adm_retry(ap
, cs
, &retries
));
654 if (cs
!= RPC_SUCCESS
)
655 return (fmd_adm_set_errno(ap
, EPROTO
));
657 return (fmd_adm_set_svcerr(ap
, err
));
661 fmd_adm_rsrc_acquit(fmd_adm_t
*ap
, const char *fmri
, const char *uuid
)
663 char *str
= (char *)fmri
;
664 char *str2
= (char *)uuid
;
670 return (fmd_adm_set_errno(ap
, EINVAL
));
673 cs
= fmd_adm_rsrcacquit_1(str
, str2
, &err
, ap
->adm_clnt
);
674 } while (fmd_adm_retry(ap
, cs
, &retries
));
676 if (cs
!= RPC_SUCCESS
)
677 return (fmd_adm_set_errno(ap
, EPROTO
));
679 return (fmd_adm_set_svcerr(ap
, err
));
683 fmd_adm_case_repair(fmd_adm_t
*ap
, const char *uuid
)
685 char *str
= (char *)uuid
;
691 return (fmd_adm_set_errno(ap
, EINVAL
));
694 cs
= fmd_adm_caserepair_1(str
, &err
, ap
->adm_clnt
);
695 } while (fmd_adm_retry(ap
, cs
, &retries
));
697 if (cs
!= RPC_SUCCESS
)
698 return (fmd_adm_set_errno(ap
, EPROTO
));
700 return (fmd_adm_set_svcerr(ap
, err
));
704 fmd_adm_case_acquit(fmd_adm_t
*ap
, const char *uuid
)
706 char *str
= (char *)uuid
;
712 return (fmd_adm_set_errno(ap
, EINVAL
));
715 cs
= fmd_adm_caseacquit_1(str
, &err
, ap
->adm_clnt
);
716 } while (fmd_adm_retry(ap
, cs
, &retries
));
718 if (cs
!= RPC_SUCCESS
)
719 return (fmd_adm_set_errno(ap
, EPROTO
));
721 return (fmd_adm_set_svcerr(ap
, err
));
725 fmd_adm_case_cmp(const void *lp
, const void *rp
)
727 return (strcmp(*(char **)lp
, *(char **)rp
));
731 fmd_adm_case_one(fmd_adm_caseinfo_t
*acp
, const char *url_token
,
732 fmd_adm_case_f
*func
, void *arg
)
734 char *p
, *urlcode
, *dict
, *olang
;
738 if ((p
= strchr(acp
->aci_code
, '-')) == NULL
||
739 p
== acp
->aci_code
) {
742 dict
= alloca((size_t)(p
- acp
->aci_code
) + 1);
743 (void) strncpy(dict
, acp
->aci_code
,
744 (size_t)(p
- acp
->aci_code
));
745 dict
[(size_t)(p
- acp
->aci_code
)] = '\0';
748 * If we're given a token to use in looking up the URL, try
749 * to use it. Otherwise, or if we don't find it that way,
752 if (url_token
== NULL
) {
754 } else if ((url
= dgettext(dict
, url_token
)) == url_token
) {
756 * We didn't find a translation in the
757 * dictionary for the current language. Fall
758 * back to C and try again.
760 olang
= setlocale(LC_MESSAGES
, NULL
);
761 (void) setlocale(LC_MESSAGES
, "C");
762 if ((url
= dgettext(dict
, url_token
)) == url_token
)
764 (void) setlocale(LC_MESSAGES
, olang
);
767 if (url
[len
- 1] == '/') {
768 len
+= strlen(acp
->aci_code
) + 1;
769 urlcode
= alloca(len
);
770 (void) snprintf(urlcode
, len
, "%s%s", url
,
773 urlcode
= (char *)url
;
775 acp
->aci_url
= urlcode
;
778 return (func(acp
, arg
));
782 * Our approach to cases is the same as for resources: we first obtain a
783 * list of UUIDs, sort them, then obtain the case information for each.
786 fmd_adm_case_iter(fmd_adm_t
*ap
, const char *url_token
, fmd_adm_case_f
*func
,
789 struct fmd_rpc_caselist rcl
;
790 struct fmd_rpc_caseinfo rci
;
791 fmd_adm_caseinfo_t aci
;
797 bzero(&rcl
, sizeof (rcl
)); /* tell xdr to allocate memory for us */
800 cs
= fmd_adm_caselist_1(&rcl
, ap
->adm_clnt
);
801 } while (fmd_adm_retry(ap
, cs
, &retries
));
803 if (cs
!= RPC_SUCCESS
)
804 return (fmd_adm_set_errno(ap
, EPROTO
));
806 if (rcl
.rcl_err
!= 0) {
807 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
808 return (fmd_adm_set_svcerr(ap
, rcl
.rcl_err
));
811 if ((uuids
= malloc(sizeof (char *) * rcl
.rcl_cnt
)) == NULL
) {
812 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
813 return (fmd_adm_set_errno(ap
, EAGAIN
));
816 p
= rcl
.rcl_buf
.rcl_buf_val
;
818 for (i
= 0; i
< rcl
.rcl_cnt
; i
++, p
+= strlen(p
) + 1)
821 qsort(uuids
, rcl
.rcl_cnt
, sizeof (char *), fmd_adm_case_cmp
);
823 for (i
= 0; i
< rcl
.rcl_cnt
; i
++) {
824 bzero(&rci
, sizeof (rci
));
828 cs
= fmd_adm_caseinfo_1(uuids
[i
], &rci
, ap
->adm_clnt
);
829 } while (fmd_adm_retry(ap
, cs
, &retries
));
831 if (cs
!= RPC_SUCCESS
) {
833 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
834 return (fmd_adm_set_errno(ap
, EPROTO
));
837 if (rci
.rci_err
!= 0 && rci
.rci_err
!= FMD_ADM_ERR_CASESRCH
) {
838 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
840 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
841 return (fmd_adm_set_svcerr(ap
, rci
.rci_err
));
844 if (rci
.rci_err
== FMD_ADM_ERR_CASESRCH
) {
845 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
849 bzero(&aci
, sizeof (aci
));
851 if ((rv
= nvlist_unpack(rci
.rci_evbuf
.rci_evbuf_val
,
852 rci
.rci_evbuf
.rci_evbuf_len
, &aci
.aci_event
, 0)) != 0) {
853 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
855 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
856 return (fmd_adm_set_errno(ap
, rv
));
859 if ((rv
= nvlist_lookup_string(aci
.aci_event
, FM_SUSPECT_UUID
,
860 (char **)&aci
.aci_uuid
)) != 0) {
861 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
863 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
864 nvlist_free(aci
.aci_event
);
865 return (fmd_adm_set_errno(ap
, rv
));
867 if ((rv
= nvlist_lookup_string(aci
.aci_event
,
868 FM_SUSPECT_DIAG_CODE
, (char **)&aci
.aci_code
)) != 0) {
869 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
871 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
872 nvlist_free(aci
.aci_event
);
873 return (fmd_adm_set_errno(ap
, rv
));
876 rv
= fmd_adm_case_one(&aci
, url_token
, func
, arg
);
878 xdr_free(xdr_fmd_rpc_caseinfo
, (char *)&rci
);
879 nvlist_free(aci
.aci_event
);
886 xdr_free(xdr_fmd_rpc_caselist
, (char *)&rcl
);
891 fmd_adm_serd_cmp(const void *lp
, const void *rp
)
893 return (strcmp(*(char **)lp
, *(char **)rp
));
897 fmd_adm_serd_iter(fmd_adm_t
*ap
, const char *name
,
898 fmd_adm_serd_f
*func
, void *arg
)
900 struct fmd_rpc_serdlist rsl
;
901 struct fmd_rpc_serdinfo rsi
;
903 fmd_adm_serdinfo_t asi
;
908 bzero(&rsl
, sizeof (rsl
)); /* tell xdr to allocate memory for us */
911 cs
= fmd_adm_serdlist_1((char *)name
, &rsl
, ap
->adm_clnt
);
912 } while (fmd_adm_retry(ap
, cs
, &retries
));
914 if (cs
!= RPC_SUCCESS
)
915 return (fmd_adm_set_errno(ap
, EPROTO
));
917 if (rsl
.rsl_err
!= 0 || rsl
.rsl_len
== 0) {
918 xdr_free(xdr_fmd_rpc_serdlist
, (char *)&rsl
);
919 return (fmd_adm_set_svcerr(ap
, rsl
.rsl_err
));
922 if ((serds
= malloc(sizeof (char *) * rsl
.rsl_cnt
)) == NULL
) {
923 xdr_free(xdr_fmd_rpc_serdlist
, (char *)&rsl
);
924 return (fmd_adm_set_errno(ap
, EAGAIN
));
927 p
= rsl
.rsl_buf
.rsl_buf_val
;
929 for (i
= 0; i
< rsl
.rsl_cnt
; i
++, p
+= strlen(p
) + 1)
932 qsort(serds
, rsl
.rsl_cnt
, sizeof (char *), fmd_adm_serd_cmp
);
934 for (i
= 0; i
< rsl
.rsl_cnt
; i
++) {
935 bzero(&rsi
, sizeof (rsi
));
939 cs
= fmd_adm_serdinfo_1((char *)name
, serds
[i
], &rsi
,
941 } while (fmd_adm_retry(ap
, cs
, &retries
));
943 if (cs
!= RPC_SUCCESS
) {
945 xdr_free(xdr_fmd_rpc_serdlist
, (char *)&rsl
);
946 return (fmd_adm_set_errno(ap
, EPROTO
));
949 if (rsi
.rsi_err
!= 0 && rsi
.rsi_err
!= FMD_ADM_ERR_SERDSRCH
) {
951 xdr_free(xdr_fmd_rpc_serdinfo
, (char *)&rsi
);
952 xdr_free(xdr_fmd_rpc_serdlist
, (char *)&rsl
);
953 return (fmd_adm_set_svcerr(ap
, rsi
.rsi_err
));
956 if (rsi
.rsi_err
== FMD_ADM_ERR_SERDSRCH
) {
957 xdr_free(xdr_fmd_rpc_serdinfo
, (char *)&rsi
);
961 bzero(&asi
, sizeof (asi
));
963 asi
.asi_name
= rsi
.rsi_name
;
964 asi
.asi_delta
= rsi
.rsi_delta
;
965 asi
.asi_n
= rsi
.rsi_n
;
966 asi
.asi_t
= rsi
.rsi_t
;
967 asi
.asi_count
= rsi
.rsi_count
;
971 asi
.asi_flags
|= FMD_ADM_SERD_FIRED
;
973 rv
= func(&asi
, arg
);
975 xdr_free(xdr_fmd_rpc_serdinfo
, (char *)&rsi
);
982 xdr_free(xdr_fmd_rpc_serdlist
, (char *)&rsl
);
987 fmd_adm_serd_reset(fmd_adm_t
*ap
, const char *mod
, const char *name
)
989 char *s1
= (char *)mod
, *s2
= (char *)name
;
994 if (mod
== NULL
|| name
== NULL
|| strchr(mod
, '/') != NULL
)
995 return (fmd_adm_set_errno(ap
, EINVAL
));
998 cs
= fmd_adm_serdreset_1(s1
, s2
, &err
, ap
->adm_clnt
);
999 } while (fmd_adm_retry(ap
, cs
, &retries
));
1001 if (cs
!= RPC_SUCCESS
)
1002 return (fmd_adm_set_errno(ap
, EPROTO
));
1004 return (fmd_adm_set_svcerr(ap
, err
));
1008 fmd_adm_xprt_iter(fmd_adm_t
*ap
, fmd_adm_xprt_f
*func
, void *arg
)
1010 struct fmd_rpc_xprtlist rxl
;
1015 bzero(&rxl
, sizeof (rxl
)); /* tell xdr to allocate memory for us */
1018 cs
= fmd_adm_xprtlist_1(&rxl
, ap
->adm_clnt
);
1019 } while (fmd_adm_retry(ap
, cs
, &retries
));
1021 if (cs
!= RPC_SUCCESS
)
1022 return (fmd_adm_set_errno(ap
, EPROTO
));
1024 if (rxl
.rxl_err
!= 0) {
1025 xdr_free(xdr_fmd_rpc_xprtlist
, (char *)&rxl
);
1026 return (fmd_adm_set_svcerr(ap
, rxl
.rxl_err
));
1029 for (i
= 0; i
< rxl
.rxl_len
; i
++)
1030 func(rxl
.rxl_buf
.rxl_buf_val
[i
], arg
);
1032 xdr_free(xdr_fmd_rpc_xprtlist
, (char *)&rxl
);
1037 fmd_adm_xprt_stats(fmd_adm_t
*ap
, id_t id
, fmd_adm_stats_t
*sp
)
1039 struct fmd_rpc_modstat rms
;
1044 return (fmd_adm_set_errno(ap
, EINVAL
));
1046 bzero(&rms
, sizeof (rms
)); /* tell xdr to allocate memory for us */
1049 cs
= fmd_adm_xprtstat_1(id
, &rms
, ap
->adm_clnt
);
1050 } while (fmd_adm_retry(ap
, cs
, &retries
));
1052 if (cs
!= RPC_SUCCESS
)
1053 return (fmd_adm_set_errno(ap
, EPROTO
));
1055 if (rms
.rms_err
!= 0) {
1056 xdr_free(xdr_fmd_rpc_modstat
, (char *)&rms
);
1057 return (fmd_adm_set_svcerr(ap
, rms
.rms_err
));
1060 sp
->ams_buf
= rms
.rms_buf
.rms_buf_val
;
1061 sp
->ams_len
= rms
.rms_buf
.rms_buf_len
;
1067 fmd_adm_log_rotate(fmd_adm_t
*ap
, const char *log
)
1074 return (fmd_adm_set_errno(ap
, EINVAL
));
1077 cs
= fmd_adm_logrotate_1((char *)log
, &err
, ap
->adm_clnt
);
1078 } while (fmd_adm_retry(ap
, cs
, &retries
));
1080 if (cs
!= RPC_SUCCESS
)
1081 return (fmd_adm_set_errno(ap
, EPROTO
));
1083 return (fmd_adm_set_svcerr(ap
, err
));
1087 * Custom XDR routine for our API structure fmd_stat_t. This function must
1088 * match the definition of fmd_stat_t in <fm/fmd_api.h> and must also match
1089 * the corresponding routine in usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c.
1092 xdr_fmd_stat(XDR
*xp
, fmd_stat_t
*sp
)
1096 rv
&= xdr_opaque(xp
, sp
->fmds_name
, sizeof (sp
->fmds_name
));
1097 rv
&= xdr_u_int(xp
, &sp
->fmds_type
);
1098 rv
&= xdr_opaque(xp
, sp
->fmds_desc
, sizeof (sp
->fmds_desc
));
1100 switch (sp
->fmds_type
) {
1102 rv
&= xdr_int(xp
, &sp
->fmds_value
.b
);
1104 case FMD_TYPE_INT32
:
1105 rv
&= xdr_int32_t(xp
, &sp
->fmds_value
.i32
);
1107 case FMD_TYPE_UINT32
:
1108 rv
&= xdr_uint32_t(xp
, &sp
->fmds_value
.ui32
);
1110 case FMD_TYPE_INT64
:
1111 rv
&= xdr_int64_t(xp
, &sp
->fmds_value
.i64
);
1113 case FMD_TYPE_UINT64
:
1116 rv
&= xdr_uint64_t(xp
, &sp
->fmds_value
.ui64
);
1118 case FMD_TYPE_STRING
:
1119 rv
&= xdr_string(xp
, &sp
->fmds_value
.str
, ~0);