1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <strings.h> 31 #include <stdlib.h> 32 #include <netdir.h> 33 #include <errno.h> 34 35 #include <fmd_adm_impl.h> 36 #include <fmd_rpc_adm.h> 37 38 static const uint_t _fmd_adm_bufsize = 128 * 1024; 39 40 fmd_adm_t * 41 fmd_adm_open(const char *host, uint32_t prog, int version) 42 { 43 fmd_adm_t *ap; 44 CLIENT *c; 45 int err; 46 rpcvers_t v; 47 48 if (version != FMD_ADM_VERSION) { 49 errno = ENOTSUP; 50 return (NULL); 51 } 52 53 if (host == NULL) 54 host = HOST_SELF; 55 56 if (prog == FMD_ADM_PROGRAM) 57 prog = FMD_ADM; 58 59 /* 60 * If we are connecting to the local host, attempt a door connection 61 * first. If that fails or we need another host, fall through to 62 * using the standard clnt_create that iterates over all transports. 63 */ 64 if (strcmp(host, HOST_SELF) == 0) 65 c = clnt_door_create(prog, FMD_ADM_VERSION_1, _fmd_adm_bufsize); 66 else 67 c = NULL; 68 69 if (c == NULL) { 70 c = clnt_create_vers(host, prog, &v, 71 FMD_ADM_VERSION_1, FMD_ADM_VERSION_1, NULL); 72 } 73 74 if (c == NULL) { 75 errno = EPROTO; 76 return (NULL); 77 } 78 79 if ((ap = malloc(sizeof (fmd_adm_t))) == NULL) { 80 err = errno; 81 clnt_destroy(c); 82 errno = err; 83 return (NULL); 84 } 85 86 ap->adm_clnt = c; 87 ap->adm_version = version; 88 ap->adm_svcerr = 0; 89 ap->adm_errno = 0; 90 91 return (ap); 92 } 93 94 void 95 fmd_adm_close(fmd_adm_t *ap) 96 { 97 if (ap == NULL) 98 return; /* permit NULL to simply caller code */ 99 100 clnt_destroy(ap->adm_clnt); 101 free(ap); 102 } 103 104 static const char * 105 fmd_adm_svc_errmsg(enum fmd_adm_error err) 106 { 107 switch (err) { 108 case FMD_ADM_ERR_NOMEM: 109 return ("unable to perform request due to allocation failure"); 110 case FMD_ADM_ERR_PERM: 111 return ("operation requires additional privilege"); 112 case FMD_ADM_ERR_MODSRCH: 113 return ("specified module is not loaded in fault manager"); 114 case FMD_ADM_ERR_MODBUSY: 115 return ("module is in use and cannot be unloaded"); 116 case FMD_ADM_ERR_MODFAIL: 117 return ("module failed and can no longer export statistics"); 118 case FMD_ADM_ERR_MODNOENT: 119 return ("file missing or cannot be accessed by fault manager"); 120 case FMD_ADM_ERR_MODEXIST: 121 return ("module using same name is already loaded"); 122 case FMD_ADM_ERR_MODINIT: 123 return ("module failed to initialize (consult fmd(1M) log)"); 124 case FMD_ADM_ERR_MODLOAD: 125 return ("module failed to load (consult fmd(1M) log)"); 126 case FMD_ADM_ERR_RSRCSRCH: 127 return ("specified resource is not cached by fault manager"); 128 case FMD_ADM_ERR_RSRCNOTF: 129 return ("specified resource is not known to be faulty"); 130 case FMD_ADM_ERR_SERDSRCH: 131 return ("specified serd engine not present in module"); 132 case FMD_ADM_ERR_SERDFIRED: 133 return ("specified serd engine has already fired"); 134 case FMD_ADM_ERR_ROTSRCH: 135 return ("invalid log file name"); 136 case FMD_ADM_ERR_ROTFAIL: 137 return ("failed to rotate log file (consult fmd(1M) log)"); 138 case FMD_ADM_ERR_ROTBUSY: 139 return ("log file is too busy to rotate (try again later)"); 140 case FMD_ADM_ERR_CASESRCH: 141 return ("specified UUID is invalid or has been repaired"); 142 case FMD_ADM_ERR_CASEOPEN: 143 return ("specified UUID is still being diagnosed"); 144 case FMD_ADM_ERR_XPRTSRCH: 145 return ("specified transport ID is invalid or has been closed"); 146 case FMD_ADM_ERR_CASEXPRT: 147 return ("specified UUID is owned by a different fault manager"); 148 default: 149 return ("unknown fault manager error"); 150 } 151 } 152 153 const char * 154 fmd_adm_errmsg(fmd_adm_t *ap) 155 { 156 if (ap == NULL) { 157 switch (errno) { 158 case ENOTSUP: 159 return ("client requires newer libfmd_adm version"); 160 case EPROTO: 161 return (clnt_spcreateerror("failed to connect to fmd")); 162 } 163 } 164 165 switch (ap ? ap->adm_errno : errno) { 166 case EPROTO: 167 return (clnt_sperror(ap->adm_clnt, "rpc call failed")); 168 case EREMOTE: 169 return (fmd_adm_svc_errmsg(ap->adm_svcerr)); 170 default: 171 return (strerror(ap->adm_errno)); 172 } 173 } 174 175 static int 176 fmd_adm_set_svcerr(fmd_adm_t *ap, enum fmd_adm_error err) 177 { 178 if (err != 0) { 179 ap->adm_svcerr = err; 180 ap->adm_errno = EREMOTE; 181 return (-1); 182 } else { 183 ap->adm_svcerr = err; 184 ap->adm_errno = 0; 185 return (0); 186 } 187 } 188 189 static int 190 fmd_adm_set_errno(fmd_adm_t *ap, int err) 191 { 192 ap->adm_errno = err; 193 errno = err; 194 return (-1); 195 } 196 197 static int 198 fmd_adm_stats_cmp(const void *lp, const void *rp) 199 { 200 return (strcmp(((fmd_stat_t *)lp)->fmds_name, 201 ((fmd_stat_t *)rp)->fmds_name)); 202 } 203 204 int 205 fmd_adm_stats_read(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp) 206 { 207 struct fmd_rpc_modstat rms; 208 enum clnt_stat cs; 209 210 if (sp == NULL) 211 return (fmd_adm_set_errno(ap, EINVAL)); 212 213 bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */ 214 215 if (name != NULL) 216 cs = fmd_adm_modcstat_1((char *)name, &rms, ap->adm_clnt); 217 else 218 cs = fmd_adm_modgstat_1(&rms, ap->adm_clnt); 219 220 if (cs != RPC_SUCCESS) 221 return (fmd_adm_set_errno(ap, EPROTO)); 222 223 if (rms.rms_err != 0) { 224 xdr_free(xdr_fmd_rpc_modstat, (char *)&rms); 225 return (fmd_adm_set_svcerr(ap, rms.rms_err)); 226 } 227 228 sp->ams_buf = rms.rms_buf.rms_buf_val; 229 sp->ams_len = rms.rms_buf.rms_buf_len; 230 231 if (sp->ams_len != 0) { 232 qsort(sp->ams_buf, sp->ams_len, 233 sizeof (fmd_stat_t), fmd_adm_stats_cmp); 234 } 235 236 return (0); 237 } 238 239 int 240 fmd_adm_stats_free(fmd_adm_t *ap, fmd_adm_stats_t *sp) 241 { 242 struct fmd_rpc_modstat rms; 243 244 if (sp == NULL) 245 return (fmd_adm_set_errno(ap, EINVAL)); 246 247 rms.rms_buf.rms_buf_val = sp->ams_buf; 248 rms.rms_buf.rms_buf_len = sp->ams_len; 249 rms.rms_err = 0; 250 251 xdr_free(xdr_fmd_rpc_modstat, (char *)&rms); 252 bzero(sp, sizeof (fmd_adm_stats_t)); 253 254 return (0); 255 } 256 257 static int 258 fmd_adm_module_cmp(const void *lp, const void *rp) 259 { 260 return (strcmp((*(struct fmd_rpc_modinfo **)lp)->rmi_name, 261 (*(struct fmd_rpc_modinfo **)rp)->rmi_name)); 262 } 263 264 int 265 fmd_adm_module_iter(fmd_adm_t *ap, fmd_adm_module_f *func, void *arg) 266 { 267 struct fmd_rpc_modinfo *rmi, **rms, **rmp; 268 struct fmd_rpc_modlist rml; 269 fmd_adm_modinfo_t ami; 270 271 bzero(&rml, sizeof (rml)); /* tell xdr to allocate memory for us */ 272 273 if (fmd_adm_modinfo_1(&rml, ap->adm_clnt) != RPC_SUCCESS) 274 return (fmd_adm_set_errno(ap, EPROTO)); 275 276 if (rml.rml_err != 0 || rml.rml_len == 0) { 277 xdr_free(xdr_fmd_rpc_modlist, (char *)&rml); 278 return (fmd_adm_set_svcerr(ap, rml.rml_err)); 279 } 280 281 if ((rms = rmp = malloc(sizeof (void *) * rml.rml_len)) == NULL) { 282 xdr_free(xdr_fmd_rpc_modlist, (char *)&rml); 283 return (fmd_adm_set_errno(ap, EAGAIN)); 284 } 285 286 for (rmi = rml.rml_list; rmi != NULL; rmi = rmi->rmi_next) 287 *rmp++ = rmi; /* store copy of pointer in array for sorting */ 288 289 qsort(rms, rml.rml_len, sizeof (void *), fmd_adm_module_cmp); 290 291 for (rmp = rms; rmp < rms + rml.rml_len; rmp++) { 292 rmi = *rmp; 293 294 ami.ami_name = rmi->rmi_name; 295 ami.ami_desc = rmi->rmi_desc; 296 ami.ami_vers = rmi->rmi_vers; 297 ami.ami_flags = 0; 298 299 if (rmi->rmi_faulty) 300 ami.ami_flags |= FMD_ADM_MOD_FAILED; 301 302 if (func(&ami, arg) != 0) 303 break; 304 } 305 306 free(rms); 307 xdr_free(xdr_fmd_rpc_modlist, (char *)&rml); 308 return (0); 309 } 310 311 int 312 fmd_adm_module_load(fmd_adm_t *ap, const char *path) 313 { 314 char *str = (char *)path; 315 int err; 316 317 if (path == NULL || path[0] != '/') 318 return (fmd_adm_set_errno(ap, EINVAL)); 319 320 if (fmd_adm_modload_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 321 return (fmd_adm_set_errno(ap, EPROTO)); 322 323 return (fmd_adm_set_svcerr(ap, err)); 324 } 325 326 int 327 fmd_adm_module_unload(fmd_adm_t *ap, const char *name) 328 { 329 char *str = (char *)name; 330 int err; 331 332 if (name == NULL || strchr(name, '/') != NULL) 333 return (fmd_adm_set_errno(ap, EINVAL)); 334 335 if (fmd_adm_modunload_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 336 return (fmd_adm_set_errno(ap, EPROTO)); 337 338 return (fmd_adm_set_svcerr(ap, err)); 339 } 340 341 int 342 fmd_adm_module_reset(fmd_adm_t *ap, const char *name) 343 { 344 char *str = (char *)name; 345 int err; 346 347 if (name == NULL || strchr(name, '/') != NULL) 348 return (fmd_adm_set_errno(ap, EINVAL)); 349 350 if (fmd_adm_modreset_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 351 return (fmd_adm_set_errno(ap, EPROTO)); 352 353 return (fmd_adm_set_svcerr(ap, err)); 354 } 355 356 int 357 fmd_adm_module_gc(fmd_adm_t *ap, const char *name) 358 { 359 char *str = (char *)name; 360 int err; 361 362 if (name == NULL || strchr(name, '/') != NULL) 363 return (fmd_adm_set_errno(ap, EINVAL)); 364 365 if (fmd_adm_modgc_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 366 return (fmd_adm_set_errno(ap, EPROTO)); 367 368 return (fmd_adm_set_svcerr(ap, err)); 369 } 370 371 int 372 fmd_adm_module_stats(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp) 373 { 374 struct fmd_rpc_modstat rms; 375 376 if (name == NULL || sp == NULL) 377 return (fmd_adm_set_errno(ap, EINVAL)); 378 379 bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */ 380 381 if (fmd_adm_moddstat_1((char *)name, &rms, ap->adm_clnt) != RPC_SUCCESS) 382 return (fmd_adm_set_errno(ap, EPROTO)); 383 384 if (rms.rms_err != 0) { 385 xdr_free(xdr_fmd_rpc_modstat, (char *)&rms); 386 return (fmd_adm_set_svcerr(ap, rms.rms_err)); 387 } 388 389 sp->ams_buf = rms.rms_buf.rms_buf_val; 390 sp->ams_len = rms.rms_buf.rms_buf_len; 391 392 return (0); 393 } 394 395 static int 396 fmd_adm_rsrc_cmp(const void *lp, const void *rp) 397 { 398 return (strcmp(*(char **)lp, *(char **)rp)); 399 } 400 401 int 402 fmd_adm_rsrc_iter(fmd_adm_t *ap, int all, fmd_adm_rsrc_f *func, void *arg) 403 { 404 struct fmd_rpc_rsrclist rrl; 405 struct fmd_rpc_rsrcinfo rri; 406 fmd_adm_rsrcinfo_t ari; 407 char **fmris, *p; 408 int i, rv; 409 410 bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */ 411 412 if (fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt) != RPC_SUCCESS) 413 return (fmd_adm_set_errno(ap, EPROTO)); 414 415 if (rrl.rrl_err != 0) { 416 xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl); 417 return (fmd_adm_set_svcerr(ap, rrl.rrl_err)); 418 } 419 420 if ((fmris = malloc(sizeof (char *) * rrl.rrl_cnt)) == NULL) { 421 xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl); 422 return (fmd_adm_set_errno(ap, EAGAIN)); 423 } 424 425 /* 426 * The fmd_adm_rsrclist_1 request returns an opaque XDR buffer that is 427 * a string table of FMRIs (e.g. "fmriA\0fmriB\0...") where rrl_cnt is 428 * the number of strings in the table and rrl_buf_val is its address. 429 * We construct an array of pointers into the string table and sort it. 430 */ 431 p = rrl.rrl_buf.rrl_buf_val; 432 433 for (i = 0; i < rrl.rrl_cnt; i++, p += strlen(p) + 1) 434 fmris[i] = p; /* store fmri pointer in array for sorting */ 435 436 qsort(fmris, rrl.rrl_cnt, sizeof (char *), fmd_adm_rsrc_cmp); 437 438 /* 439 * For each FMRI in the resource cache snapshot, use fmd_adm_rsrcinfo_1 440 * to get more information and the invoke the callback function. If 441 * FMD_ADM_ERR_RSRCSRCH is returned, the FMRI has been purged from the 442 * cache since our snapshot: this error is therefore silently ignored. 443 */ 444 for (i = 0; i < rrl.rrl_cnt; i++) { 445 bzero(&rri, sizeof (rri)); 446 447 if (fmd_adm_rsrcinfo_1(fmris[i], &rri, 448 ap->adm_clnt) != RPC_SUCCESS) { 449 free(fmris); 450 xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl); 451 return (fmd_adm_set_errno(ap, EPROTO)); 452 } 453 454 if (rri.rri_err != 0 && rri.rri_err != FMD_ADM_ERR_RSRCSRCH) { 455 xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri); 456 free(fmris); 457 xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl); 458 return (fmd_adm_set_svcerr(ap, rri.rri_err)); 459 } 460 461 if (rri.rri_err == FMD_ADM_ERR_RSRCSRCH) { 462 xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri); 463 continue; 464 } 465 466 ari.ari_fmri = rri.rri_fmri; 467 ari.ari_uuid = rri.rri_uuid; 468 ari.ari_case = rri.rri_case; 469 ari.ari_flags = 0; 470 471 if (rri.rri_faulty) 472 ari.ari_flags |= FMD_ADM_RSRC_FAULTY; 473 if (rri.rri_unusable) 474 ari.ari_flags |= FMD_ADM_RSRC_UNUSABLE; 475 if (rri.rri_invisible) 476 ari.ari_flags |= FMD_ADM_RSRC_INVISIBLE; 477 478 rv = func(&ari, arg); 479 xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri); 480 481 if (rv != 0) 482 break; 483 } 484 485 free(fmris); 486 xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl); 487 return (0); 488 } 489 490 int 491 fmd_adm_rsrc_flush(fmd_adm_t *ap, const char *fmri) 492 { 493 char *str = (char *)fmri; 494 int err; 495 496 if (fmri == NULL) 497 return (fmd_adm_set_errno(ap, EINVAL)); 498 499 if (fmd_adm_rsrcflush_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 500 return (fmd_adm_set_errno(ap, EPROTO)); 501 502 return (fmd_adm_set_svcerr(ap, err)); 503 } 504 505 int 506 fmd_adm_rsrc_repair(fmd_adm_t *ap, const char *fmri) 507 { 508 char *str = (char *)fmri; 509 int err; 510 511 if (fmri == NULL) 512 return (fmd_adm_set_errno(ap, EINVAL)); 513 514 if (fmd_adm_rsrcrepair_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 515 return (fmd_adm_set_errno(ap, EPROTO)); 516 517 return (fmd_adm_set_svcerr(ap, err)); 518 } 519 520 int 521 fmd_adm_case_repair(fmd_adm_t *ap, const char *uuid) 522 { 523 char *str = (char *)uuid; 524 int err; 525 526 if (uuid == NULL) 527 return (fmd_adm_set_errno(ap, EINVAL)); 528 529 if (fmd_adm_caserepair_1(str, &err, ap->adm_clnt) != RPC_SUCCESS) 530 return (fmd_adm_set_errno(ap, EPROTO)); 531 532 return (fmd_adm_set_svcerr(ap, err)); 533 } 534 535 static int 536 fmd_adm_serd_cmp(const void *lp, const void *rp) 537 { 538 return (strcmp((*(struct fmd_rpc_serdinfo **)lp)->rsi_name, 539 (*(struct fmd_rpc_serdinfo **)rp)->rsi_name)); 540 } 541 542 int 543 fmd_adm_serd_iter(fmd_adm_t *ap, const char *name, 544 fmd_adm_serd_f *func, void *arg) 545 { 546 struct fmd_rpc_serdinfo *rsi, **ris, **rip; 547 struct fmd_rpc_serdlist rsl; 548 fmd_adm_serdinfo_t asi; 549 550 bzero(&rsl, sizeof (rsl)); /* tell xdr to allocate memory for us */ 551 552 if (fmd_adm_serdinfo_1((char *)name, &rsl, ap->adm_clnt) != RPC_SUCCESS) 553 return (fmd_adm_set_errno(ap, EPROTO)); 554 555 if (rsl.rsl_err != 0 || rsl.rsl_len == 0) { 556 xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl); 557 return (fmd_adm_set_svcerr(ap, rsl.rsl_err)); 558 } 559 560 if ((ris = rip = malloc(sizeof (void *) * rsl.rsl_len)) == NULL) { 561 xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl); 562 return (fmd_adm_set_errno(ap, EAGAIN)); 563 } 564 565 for (rsi = rsl.rsl_list; rsi != NULL; rsi = rsi->rsi_next) 566 *rip++ = rsi; /* store copy of pointer in array for sorting */ 567 568 qsort(ris, rsl.rsl_len, sizeof (void *), fmd_adm_serd_cmp); 569 570 for (rip = ris; rip < ris + rsl.rsl_len; rip++) { 571 rsi = *rip; 572 573 asi.asi_name = rsi->rsi_name; 574 asi.asi_delta = rsi->rsi_delta; 575 asi.asi_n = rsi->rsi_n; 576 asi.asi_t = rsi->rsi_t; 577 asi.asi_count = rsi->rsi_count; 578 asi.asi_flags = 0; 579 580 if (rsi->rsi_fired) 581 asi.asi_flags |= FMD_ADM_SERD_FIRED; 582 583 if (func(&asi, arg) != 0) 584 break; 585 } 586 587 free(ris); 588 xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl); 589 return (0); 590 } 591 592 int 593 fmd_adm_serd_reset(fmd_adm_t *ap, const char *mod, const char *name) 594 { 595 char *s1 = (char *)mod, *s2 = (char *)name; 596 int err; 597 598 if (mod == NULL || name == NULL || strchr(mod, '/') != NULL) 599 return (fmd_adm_set_errno(ap, EINVAL)); 600 601 if (fmd_adm_serdreset_1(s1, s2, &err, ap->adm_clnt) != RPC_SUCCESS) 602 return (fmd_adm_set_errno(ap, EPROTO)); 603 604 return (fmd_adm_set_svcerr(ap, err)); 605 } 606 607 int 608 fmd_adm_xprt_iter(fmd_adm_t *ap, fmd_adm_xprt_f *func, void *arg) 609 { 610 struct fmd_rpc_xprtlist rxl; 611 uint_t i; 612 613 bzero(&rxl, sizeof (rxl)); /* tell xdr to allocate memory for us */ 614 615 if (fmd_adm_xprtlist_1(&rxl, ap->adm_clnt) != RPC_SUCCESS) 616 return (fmd_adm_set_errno(ap, EPROTO)); 617 618 if (rxl.rxl_err != 0) { 619 xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl); 620 return (fmd_adm_set_svcerr(ap, rxl.rxl_err)); 621 } 622 623 for (i = 0; i < rxl.rxl_len; i++) 624 func(rxl.rxl_buf.rxl_buf_val[i], arg); 625 626 xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl); 627 return (0); 628 } 629 630 int 631 fmd_adm_xprt_stats(fmd_adm_t *ap, id_t id, fmd_adm_stats_t *sp) 632 { 633 struct fmd_rpc_modstat rms; 634 635 if (sp == NULL) 636 return (fmd_adm_set_errno(ap, EINVAL)); 637 638 bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */ 639 640 if (fmd_adm_xprtstat_1(id, &rms, ap->adm_clnt) != RPC_SUCCESS) 641 return (fmd_adm_set_errno(ap, EPROTO)); 642 643 if (rms.rms_err != 0) { 644 xdr_free(xdr_fmd_rpc_modstat, (char *)&rms); 645 return (fmd_adm_set_svcerr(ap, rms.rms_err)); 646 } 647 648 sp->ams_buf = rms.rms_buf.rms_buf_val; 649 sp->ams_len = rms.rms_buf.rms_buf_len; 650 651 return (0); 652 } 653 654 int 655 fmd_adm_log_rotate(fmd_adm_t *ap, const char *log) 656 { 657 int err; 658 659 if (log == NULL) 660 return (fmd_adm_set_errno(ap, EINVAL)); 661 662 if (fmd_adm_logrotate_1((char *)log, &err, ap->adm_clnt) != RPC_SUCCESS) 663 return (fmd_adm_set_errno(ap, EPROTO)); 664 665 return (fmd_adm_set_svcerr(ap, err)); 666 } 667 668 /* 669 * Custom XDR routine for our API structure fmd_stat_t. This function must 670 * match the definition of fmd_stat_t in <fm/fmd_api.h> and must also match 671 * the corresponding routine in usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c. 672 */ 673 bool_t 674 xdr_fmd_stat(XDR *xp, fmd_stat_t *sp) 675 { 676 bool_t rv = TRUE; 677 678 rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name)); 679 rv &= xdr_u_int(xp, &sp->fmds_type); 680 rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc)); 681 682 switch (sp->fmds_type) { 683 case FMD_TYPE_BOOL: 684 rv &= xdr_int(xp, &sp->fmds_value.bool); 685 break; 686 case FMD_TYPE_INT32: 687 rv &= xdr_int32_t(xp, &sp->fmds_value.i32); 688 break; 689 case FMD_TYPE_UINT32: 690 rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32); 691 break; 692 case FMD_TYPE_INT64: 693 rv &= xdr_int64_t(xp, &sp->fmds_value.i64); 694 break; 695 case FMD_TYPE_UINT64: 696 case FMD_TYPE_TIME: 697 case FMD_TYPE_SIZE: 698 rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64); 699 break; 700 case FMD_TYPE_STRING: 701 rv &= xdr_string(xp, &sp->fmds_value.str, ~0); 702 break; 703 } 704 705 return (rv); 706 } 707