Print this page
patch cleanup
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/librcm/librcm.c
+++ new/usr/src/lib/librcm/librcm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 #include "librcm_impl.h"
29 27 #include "librcm_event.h"
30 28
31 29 #ifdef DEBUG
32 30 static int rcm_debug = 1;
33 31 #define dprintf(args) if (rcm_debug) (void) fprintf args
34 32 #else
35 33 #define dprintf(args) /* nothing */
36 34 #endif /* DEBUG */
37 35
38 36 static int extract_info(nvlist_t *, rcm_info_t **);
39 37 static int rcm_daemon_is_alive();
40 38 static int rcm_common(int, rcm_handle_t *, char **, uint_t, void *,
41 39 rcm_info_t **);
42 40 static int rcm_direct_call(int, rcm_handle_t *, char **, uint_t, void *,
43 41 rcm_info_t **);
44 42 static int rcm_daemon_call(int, rcm_handle_t *, char **, uint_t, void *,
45 43 rcm_info_t **);
46 44 static int rcm_generate_nvlist(int, rcm_handle_t *, char **, uint_t, void *,
47 45 char **, size_t *);
48 46 static int rcm_check_permission(void);
49 47
50 48 /*
51 49 * Allocate a handle structure
52 50 */
53 51 /*ARGSUSED2*/
54 52 int
55 53 rcm_alloc_handle(char *modname, uint_t flag, void *arg, rcm_handle_t **hdp)
56 54 {
57 55 rcm_handle_t *hd;
58 56 void *temp;
59 57 char namebuf[MAXPATHLEN];
60 58
61 59 if ((hdp == NULL) || (flag & ~RCM_ALLOC_HDL_MASK)) {
62 60 errno = EINVAL;
63 61 return (RCM_FAILURE);
64 62 }
65 63
66 64 if (rcm_check_permission() == 0) {
67 65 errno = EPERM;
68 66 return (RCM_FAILURE);
69 67 }
70 68
71 69 if ((hd = calloc(1, sizeof (*hd))) == NULL) {
72 70 return (RCM_FAILURE);
73 71 }
74 72
75 73 if (modname) {
76 74 (void) snprintf(namebuf, MAXPATHLEN, "%s%s", modname,
77 75 RCM_MODULE_SUFFIX);
78 76
79 77 if ((hd->modname = strdup(namebuf)) == NULL) {
80 78 free(hd);
81 79 return (RCM_FAILURE);
82 80 }
83 81
84 82 if ((temp = rcm_module_open(namebuf)) == NULL) {
85 83 free(hd->modname);
86 84 free(hd);
87 85 errno = EINVAL;
88 86 return (RCM_FAILURE);
89 87 }
90 88
91 89 rcm_module_close(temp);
92 90 }
93 91
94 92 if (flag & RCM_NOPID) {
95 93 hd->pid = (pid_t)0;
96 94 } else {
97 95 hd->pid = (pid_t)getpid();
98 96 }
99 97
100 98 *hdp = hd;
101 99 return (RCM_SUCCESS);
102 100 }
103 101
104 102 /* free handle structure */
105 103 int
106 104 rcm_free_handle(rcm_handle_t *hd)
107 105 {
108 106 if (hd == NULL) {
109 107 errno = EINVAL;
110 108 return (RCM_FAILURE);
111 109 }
112 110
113 111 if (hd->modname) {
114 112 free(hd->modname);
115 113 }
116 114
117 115 free(hd);
118 116 return (RCM_SUCCESS);
119 117 }
120 118
121 119
122 120 /*
123 121 * Operations which require daemon processing
124 122 */
125 123
126 124 /* get registration and DR information from rcm_daemon */
127 125 int
128 126 rcm_get_info(rcm_handle_t *hd, char *rsrcname, uint_t flag, rcm_info_t **infop)
129 127 {
130 128 char *rsrcnames[2];
131 129
132 130 if ((flag & ~RCM_GET_INFO_MASK) || (infop == NULL)) {
133 131 errno = EINVAL;
134 132 return (RCM_FAILURE);
135 133 }
136 134
137 135 /*
138 136 * rsrcname may be NULL if requesting dr operations or modinfo
139 137 */
140 138 if ((rsrcname == NULL) &&
141 139 ((flag & RCM_DR_OPERATION|RCM_MOD_INFO) == 0)) {
142 140 errno = EINVAL;
143 141 return (RCM_FAILURE);
144 142 }
145 143
146 144 rsrcnames[0] = rsrcname;
147 145 rsrcnames[1] = NULL;
148 146
149 147 return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop));
150 148 }
151 149
152 150 /* get registration and DR information from rcm_daemon (list version) */
153 151 int
154 152 rcm_get_info_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
155 153 rcm_info_t **infop)
156 154 {
157 155 /* Requesting the current DR operations with a *list() is invalid */
158 156 if ((flag & RCM_DR_OPERATION) || (flag & RCM_MOD_INFO)) {
159 157 errno = EINVAL;
160 158 return (RCM_FAILURE);
161 159 }
162 160
163 161 return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop));
164 162 }
165 163
166 164 /* request to offline a resource before DR removal */
167 165 int
168 166 rcm_request_offline(rcm_handle_t *hd, char *rsrcname, uint_t flag,
169 167 rcm_info_t **infop)
170 168 {
171 169 char *rsrcnames[2];
172 170
173 171 rsrcnames[0] = rsrcname;
174 172 rsrcnames[1] = NULL;
175 173
176 174 return (rcm_request_offline_list(hd, rsrcnames, flag, infop));
177 175 }
178 176
179 177 /* request to offline a resource before DR removal (list version) */
180 178 int
181 179 rcm_request_offline_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
182 180 rcm_info_t **infop)
183 181 {
184 182 if (flag & ~RCM_REQUEST_MASK) {
185 183 errno = EINVAL;
186 184 return (RCM_FAILURE);
187 185 }
188 186
189 187 return (rcm_common(CMD_OFFLINE, hd, rsrcnames, flag, NULL, infop));
190 188 }
191 189
192 190 /* cancel offline request and allow apps to use rsrcname */
193 191 int
194 192 rcm_notify_online(rcm_handle_t *hd, char *rsrcname, uint_t flag,
195 193 rcm_info_t **infop)
196 194 {
197 195 char *rsrcnames[2];
198 196
199 197 rsrcnames[0] = rsrcname;
200 198 rsrcnames[1] = NULL;
201 199
202 200 return (rcm_notify_online_list(hd, rsrcnames, flag, infop));
203 201 }
204 202
205 203 /* cancel offline and allow apps to use resources (list version) */
206 204 int
207 205 rcm_notify_online_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
208 206 rcm_info_t **infop)
209 207 {
210 208 if (flag & ~RCM_NOTIFY_MASK) {
211 209 errno = EINVAL;
212 210 return (RCM_FAILURE);
213 211 }
214 212
215 213 return (rcm_common(CMD_ONLINE, hd, rsrcnames, flag, NULL, infop));
216 214 }
217 215
218 216 /* notify that rsrcname has been removed */
219 217 int
220 218 rcm_notify_remove(rcm_handle_t *hd, char *rsrcname, uint_t flag,
221 219 rcm_info_t **infop)
222 220 {
223 221 char *rsrcnames[2];
224 222
225 223 rsrcnames[0] = rsrcname;
226 224 rsrcnames[1] = NULL;
227 225
228 226 return (rcm_notify_remove_list(hd, rsrcnames, flag, infop));
229 227 }
230 228
231 229 /* notify that resrouces have been removed (list form) */
232 230 int
233 231 rcm_notify_remove_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
234 232 rcm_info_t **infop)
235 233 {
236 234 if (flag & ~RCM_NOTIFY_MASK) {
237 235 errno = EINVAL;
238 236 return (RCM_FAILURE);
239 237 }
240 238
241 239 return (rcm_common(CMD_REMOVE, hd, rsrcnames, flag, NULL, infop));
242 240 }
243 241
244 242 /* request for permission to suspend resource of interval time */
245 243 int
246 244 rcm_request_suspend(rcm_handle_t *hd, char *rsrcname, uint_t flag,
247 245 timespec_t *interval, rcm_info_t **infop)
248 246 {
249 247 char *rsrcnames[2];
250 248
251 249 rsrcnames[0] = rsrcname;
252 250 rsrcnames[1] = NULL;
253 251
254 252 return (rcm_request_suspend_list(hd, rsrcnames, flag, interval, infop));
255 253 }
256 254
257 255 /* request for permission to suspend resource of interval time (list form) */
258 256 int
259 257 rcm_request_suspend_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
260 258 timespec_t *interval, rcm_info_t **infop)
261 259 {
262 260 if ((flag & ~RCM_REQUEST_MASK) || (interval == NULL) ||
263 261 (interval->tv_sec < 0) || (interval->tv_nsec < 0)) {
264 262 errno = EINVAL;
265 263 return (RCM_FAILURE);
266 264 }
267 265
268 266 return (rcm_common(CMD_SUSPEND, hd, rsrcnames, flag, (void *)interval,
269 267 infop));
270 268 }
271 269
272 270 /* notify apps of the completion of resource suspension */
273 271 int
274 272 rcm_notify_resume(rcm_handle_t *hd, char *rsrcname, uint_t flag,
275 273 rcm_info_t **infop)
276 274 {
277 275 char *rsrcnames[2];
278 276
279 277 rsrcnames[0] = rsrcname;
280 278 rsrcnames[1] = NULL;
281 279
282 280 return (rcm_notify_resume_list(hd, rsrcnames, flag, infop));
283 281 }
284 282
285 283 /* notify apps of the completion of resource suspension (list form) */
286 284 int
287 285 rcm_notify_resume_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag,
288 286 rcm_info_t **infop)
289 287 {
290 288 if (flag & ~(RCM_NOTIFY_MASK | RCM_SUSPENDED)) {
291 289 errno = EINVAL;
292 290 return (RCM_FAILURE);
293 291 }
294 292
295 293 return (rcm_common(CMD_RESUME, hd, rsrcnames, flag, NULL, infop));
296 294 }
297 295
298 296 /* request a capacity change from apps */
299 297 int
300 298 rcm_request_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag,
301 299 nvlist_t *nvl, rcm_info_t **infop)
302 300 {
303 301 int rv;
304 302 char *rsrcnames[2];
305 303
306 304 if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) {
307 305 errno = EINVAL;
308 306 return (RCM_FAILURE);
309 307 }
310 308
311 309 rsrcnames[0] = rsrcname;
312 310 rsrcnames[1] = NULL;
313 311
314 312 rv = rcm_common(CMD_REQUEST_CHANGE, hd, rsrcnames, flag, (void *)nvl,
315 313 infop);
316 314
317 315 return (rv);
318 316 }
319 317
320 318 /* notify apps of a capacity change */
321 319 int
322 320 rcm_notify_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag,
323 321 nvlist_t *nvl, rcm_info_t **infop)
324 322 {
325 323 int rv;
326 324 char *rsrcnames[2];
327 325
328 326 if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) {
329 327 errno = EINVAL;
330 328 return (RCM_FAILURE);
331 329 }
332 330
333 331 rsrcnames[0] = rsrcname;
334 332 rsrcnames[1] = NULL;
335 333
336 334 rv = rcm_common(CMD_NOTIFY_CHANGE, hd, rsrcnames, flag, (void *)nvl,
337 335 infop);
338 336
339 337 return (rv);
340 338 }
341 339
342 340 /* notify apps of an event */
343 341 int
344 342 rcm_notify_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, nvlist_t *nvl,
345 343 rcm_info_t **infop)
346 344 {
347 345 int rv;
348 346 char *rsrcnames[2];
349 347
350 348 /* No flags are defined yet for rcm_notify_event() */
351 349 if ((nvl == NULL) || (flag != 0)) {
352 350 errno = EINVAL;
353 351 return (RCM_FAILURE);
354 352 }
355 353
356 354 rsrcnames[0] = rsrcname;
357 355 rsrcnames[1] = NULL;
358 356
359 357 rv = rcm_common(CMD_EVENT, hd, rsrcnames, 0, (void *)nvl, infop);
360 358
361 359 return (rv);
362 360 }
363 361
364 362 /*
365 363 * Register to receive capacity changes. This requires a module to exist in
366 364 * module directory. It should be called prior to using a new resource.
367 365 */
368 366 /* ARGSUSED */
369 367 int
370 368 rcm_register_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag,
371 369 rcm_info_t **infop)
372 370 {
373 371 char *rsrcnames[2];
374 372
375 373 if (flag & ~RCM_REGISTER_MASK) {
376 374 errno = EINVAL;
377 375 return (RCM_FAILURE);
378 376 }
379 377
380 378 flag |= RCM_REGISTER_CAPACITY;
381 379
382 380 rsrcnames[0] = rsrcname;
383 381 rsrcnames[1] = NULL;
384 382
385 383 return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL));
386 384 }
387 385
388 386 /* unregister interest in capacity changes */
389 387 int
390 388 rcm_unregister_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag)
391 389 {
392 390 char *rsrcnames[2];
393 391
394 392 if (flag & ~RCM_REGISTER_MASK) {
395 393 errno = EINVAL;
396 394 return (RCM_FAILURE);
397 395 }
398 396
399 397 flag |= RCM_REGISTER_CAPACITY;
400 398
401 399 rsrcnames[0] = rsrcname;
402 400 rsrcnames[1] = NULL;
403 401
404 402 return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL));
405 403 }
406 404
407 405 /*
408 406 * Register to receive events. This requires a module to exist in module
409 407 * directory. It should be called prior to using a new resource.
410 408 */
411 409 /* ARGSUSED */
412 410 int
413 411 rcm_register_event(rcm_handle_t *hd, char *rsrcname, uint_t flag,
414 412 rcm_info_t **infop)
415 413 {
416 414 char *rsrcnames[2];
417 415
418 416 if (flag & ~RCM_REGISTER_MASK) {
419 417 errno = EINVAL;
420 418 return (RCM_FAILURE);
421 419 }
422 420
423 421 flag |= RCM_REGISTER_EVENT;
424 422
425 423 rsrcnames[0] = rsrcname;
426 424 rsrcnames[1] = NULL;
427 425
428 426 return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL));
429 427 }
430 428
431 429 /* unregister interest in events */
432 430 int
433 431 rcm_unregister_event(rcm_handle_t *hd, char *rsrcname, uint_t flag)
434 432 {
435 433 char *rsrcnames[2];
436 434
437 435 if (flag & ~RCM_REGISTER_MASK) {
438 436 errno = EINVAL;
439 437 return (RCM_FAILURE);
440 438 }
441 439
442 440 flag |= RCM_REGISTER_EVENT;
443 441
444 442 rsrcnames[0] = rsrcname;
445 443 rsrcnames[1] = NULL;
446 444
447 445 return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL));
448 446 }
449 447
450 448 /*
451 449 * Register interest in a resource. This requires a module to exist in module
452 450 * directory. It should be called prior to using a new resource.
453 451 *
454 452 * Registration may be denied if it is presently locked by a DR operation.
455 453 */
456 454 /* ARGSUSED */
457 455 int
458 456 rcm_register_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag,
459 457 rcm_info_t **infop)
460 458 {
461 459 char *rsrcnames[2];
462 460
463 461 if (flag & ~RCM_REGISTER_MASK) {
464 462 errno = EINVAL;
465 463 return (RCM_FAILURE);
466 464 }
467 465
468 466 flag |= RCM_REGISTER_DR;
469 467
470 468 rsrcnames[0] = rsrcname;
471 469 rsrcnames[1] = NULL;
472 470
473 471 return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL));
474 472 }
475 473
476 474 /* unregister interest in rsrcname */
477 475 int
478 476 rcm_unregister_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag)
479 477 {
480 478 char *rsrcnames[2];
481 479
482 480 if (flag & ~RCM_REGISTER_MASK) {
483 481 errno = EINVAL;
484 482 return (RCM_FAILURE);
485 483 }
486 484
487 485 flag |= RCM_REGISTER_DR;
488 486
489 487 rsrcnames[0] = rsrcname;
490 488 rsrcnames[1] = NULL;
491 489
492 490 return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL));
493 491 }
494 492
495 493 /* get the current state of a resource */
496 494 int
497 495 rcm_get_rsrcstate(rcm_handle_t *hd, char *rsrcname, int *statep)
498 496 {
499 497 int result;
500 498 int flag = 0;
501 499 rcm_info_t *infop = NULL;
502 500 rcm_info_tuple_t *tuple = NULL;
503 501 char *rsrcnames[2];
504 502
505 503 if (statep == NULL) {
506 504 errno = EINVAL;
507 505 return (RCM_FAILURE);
508 506 }
509 507
510 508 rsrcnames[0] = rsrcname;
511 509 rsrcnames[1] = NULL;
512 510
513 511 result = rcm_common(CMD_GETSTATE, hd, rsrcnames, flag, NULL, &infop);
514 512
515 513 /*
516 514 * A successful result implies the presence of exactly one RCM info
517 515 * tuple containing the state of this resource (a combination of each
518 516 * client's resources). If that's not true, change the result to
519 517 * RCM_FAILURE.
520 518 */
521 519 if (result == RCM_SUCCESS) {
522 520 if ((infop == NULL) ||
523 521 ((tuple = rcm_info_next(infop, NULL)) == NULL) ||
524 522 (rcm_info_next(infop, tuple) != NULL)) {
525 523 result = RCM_FAILURE;
526 524 } else if (infop && tuple) {
527 525 *statep = rcm_info_state(tuple);
528 526 }
529 527 }
530 528
531 529 if (infop)
532 530 rcm_free_info(infop);
533 531
534 532 return (result);
535 533 }
536 534
537 535 /*
↓ open down ↓ |
500 lines elided |
↑ open up ↑ |
538 536 * RCM helper functions exposed to librcm callers.
539 537 */
540 538
541 539 /* Free linked list of registration info */
542 540 void
543 541 rcm_free_info(rcm_info_t *info)
544 542 {
545 543 while (info) {
546 544 rcm_info_t *tmp = info->next;
547 545
548 - if (info->info)
549 - nvlist_free(info->info);
546 + nvlist_free(info->info);
550 547 free(info);
551 548
552 549 info = tmp;
553 550 }
554 551 }
555 552
556 553 /* return the next tuple in the info structure */
557 554 rcm_info_tuple_t *
558 555 rcm_info_next(rcm_info_t *info, rcm_info_tuple_t *tuple)
559 556 {
560 557 if (info == NULL) {
561 558 errno = EINVAL;
562 559 return (NULL);
563 560 }
564 561
565 562 if (tuple == NULL) {
566 563 return ((rcm_info_tuple_t *)info);
567 564 }
568 565 return ((rcm_info_tuple_t *)tuple->next);
569 566 }
570 567
571 568 /* return resource name */
572 569 const char *
573 570 rcm_info_rsrc(rcm_info_tuple_t *tuple)
574 571 {
575 572 char *rsrcname = NULL;
576 573
577 574 if (tuple == NULL || tuple->info == NULL) {
578 575 errno = EINVAL;
579 576 return (NULL);
580 577 }
581 578
582 579 if (errno = nvlist_lookup_string(tuple->info, RCM_RSRCNAME, &rsrcname))
583 580 return (NULL);
584 581
585 582 return (rsrcname);
586 583 }
587 584
588 585 const char *
589 586 rcm_info_info(rcm_info_tuple_t *tuple)
590 587 {
591 588 char *info = NULL;
592 589
593 590 if (tuple == NULL || tuple->info == NULL) {
594 591 errno = EINVAL;
595 592 return (NULL);
596 593 }
597 594
598 595 if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_INFO, &info))
599 596 return (NULL);
600 597
601 598 return (info);
602 599 }
603 600
604 601 const char *
605 602 rcm_info_error(rcm_info_tuple_t *tuple)
606 603 {
607 604 char *errstr = NULL;
608 605
609 606 if (tuple == NULL || tuple->info == NULL) {
610 607 errno = EINVAL;
611 608 return (NULL);
612 609 }
613 610
614 611 if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_ERROR,
615 612 &errstr))
616 613 return (NULL);
617 614
618 615 return (errstr);
619 616 }
620 617
621 618 /* return info string in the tuple */
622 619 const char *
623 620 rcm_info_modname(rcm_info_tuple_t *tuple)
624 621 {
625 622 char *modname = NULL;
626 623
627 624 if (tuple == NULL || tuple->info == NULL) {
628 625 errno = EINVAL;
629 626 return (NULL);
630 627 }
631 628
632 629 if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_MODNAME,
633 630 &modname))
634 631 return (NULL);
635 632
636 633 return (modname);
637 634 }
638 635
639 636 /* return client pid in the tuple */
640 637 pid_t
641 638 rcm_info_pid(rcm_info_tuple_t *tuple)
642 639 {
643 640 uint64_t pid64 = (uint64_t)0;
644 641
645 642 if (tuple == NULL || tuple->info == NULL) {
646 643 errno = EINVAL;
647 644 return ((pid_t)0);
648 645 }
649 646
650 647 if (errno = nvlist_lookup_uint64(tuple->info, RCM_CLIENT_ID, &pid64))
651 648 return ((pid_t)0);
652 649
653 650 return ((pid_t)pid64);
654 651 }
655 652
656 653 /* return client state in the tuple */
657 654 int
658 655 rcm_info_state(rcm_info_tuple_t *tuple)
659 656 {
660 657 int state;
661 658
662 659 if (tuple == NULL || tuple->info == NULL) {
663 660 errno = EINVAL;
664 661 return (RCM_STATE_UNKNOWN);
665 662 }
666 663
667 664 if (errno = nvlist_lookup_int32(tuple->info, RCM_RSRCSTATE, &state))
668 665 return (RCM_STATE_UNKNOWN);
669 666
670 667 return (state);
671 668 }
672 669
673 670 /* return the generic properties in the tuple */
674 671 nvlist_t *
675 672 rcm_info_properties(rcm_info_tuple_t *tuple)
676 673 {
677 674 char *buf;
678 675 uint_t buflen;
679 676 nvlist_t *nvl;
680 677
681 678 if (tuple == NULL || tuple->info == NULL) {
682 679 errno = EINVAL;
683 680 return (NULL);
684 681 }
685 682
686 683 if (errno = nvlist_lookup_byte_array(tuple->info, RCM_CLIENT_PROPERTIES,
687 684 (uchar_t **)&buf, &buflen))
688 685 return (NULL);
689 686
690 687 if (errno = nvlist_unpack(buf, buflen, &nvl, 0)) {
691 688 free(buf);
692 689 return (NULL);
693 690 }
694 691
695 692 return (nvl);
696 693 }
697 694
698 695 /*
699 696 * return operation sequence number
700 697 *
701 698 * This is private. Called by rcmctl only for testing purposes.
702 699 */
703 700 int
704 701 rcm_info_seqnum(rcm_info_tuple_t *tuple)
705 702 {
706 703 int seqnum;
707 704
708 705 if (tuple == NULL || tuple->info == NULL) {
709 706 errno = EINVAL;
710 707 return (-1);
711 708 }
712 709
713 710 if (errno = nvlist_lookup_int32(tuple->info, RCM_SEQ_NUM, &seqnum))
714 711 return (-1);
715 712
716 713 return (seqnum);
717 714 }
718 715
719 716
720 717 /*
721 718 * The following interfaces are PRIVATE to the RCM framework. They are not
722 719 * declared static because they are called by rcm_daemon.
723 720 */
724 721
725 722 /*
726 723 * Invoke shell to execute command in MT safe manner.
727 724 * Returns wait status or -1 on error.
728 725 */
729 726 int
730 727 rcm_exec_cmd(char *cmd)
731 728 {
732 729 pid_t pid;
733 730 int status, w;
734 731 char *argvec[] = {"sh", "-c", NULL, NULL};
735 732
736 733 argvec[2] = cmd;
737 734 if ((pid = fork1()) == 0) {
738 735 (void) execv("/bin/sh", argvec);
739 736 _exit(127);
740 737 } else if (pid == -1) {
741 738 return (-1);
742 739 }
743 740
744 741 do {
745 742 w = waitpid(pid, &status, 0);
746 743 } while (w == -1 && errno == EINTR);
747 744
748 745 return ((w == -1) ? w : status);
749 746 }
750 747
751 748 /* Append info at the very end */
752 749 int
753 750 rcm_append_info(rcm_info_t **head, rcm_info_t *info)
754 751 {
755 752 rcm_info_t *tuple;
756 753
757 754 if (head == NULL) {
758 755 errno = EINVAL;
759 756 return (RCM_FAILURE);
760 757 }
761 758
762 759 if ((tuple = *head) == NULL) {
763 760 *head = info;
764 761 return (RCM_SUCCESS);
765 762 }
766 763
767 764 while (tuple->next) {
768 765 tuple = tuple->next;
769 766 }
770 767 tuple->next = info;
771 768 return (RCM_SUCCESS);
772 769 }
773 770
774 771 /* get rcm module and rcm script directory names */
775 772
776 773 #define N_MODULE_DIR 3 /* search 3 directories for modules */
777 774 #define MODULE_DIR_HW "/usr/platform/%s/lib/rcm/modules/"
778 775 #define MODULE_DIR_GEN "/usr/lib/rcm/modules/"
779 776
780 777 #define N_SCRIPT_DIR 4 /* search 4 directories for scripts */
781 778 #define SCRIPT_DIR_HW "/usr/platform/%s/lib/rcm/scripts/"
782 779 #define SCRIPT_DIR_GEN "/usr/lib/rcm/scripts/"
783 780 #define SCRIPT_DIR_ETC "/etc/rcm/scripts/"
784 781
785 782
786 783 char *
787 784 rcm_module_dir(uint_t dirnum)
788 785 {
789 786 if (dirnum < N_MODULE_DIR)
790 787 return (rcm_dir(dirnum, NULL));
791 788 else
792 789 return (NULL);
793 790 }
794 791
795 792 char *
796 793 rcm_script_dir(uint_t dirnum)
797 794 {
798 795 if (dirnum < N_SCRIPT_DIR)
799 796 return (rcm_dir(dirnum + N_MODULE_DIR, NULL));
800 797 else
801 798 return (NULL);
802 799 }
803 800
804 801 char *
805 802 rcm_dir(uint_t dirnum, int *rcm_script)
806 803 {
807 804 static char dir_name[N_MODULE_DIR + N_SCRIPT_DIR][MAXPATHLEN];
808 805
809 806 char infobuf[MAXPATHLEN];
810 807
811 808 if (dirnum >= (N_MODULE_DIR + N_SCRIPT_DIR))
812 809 return (NULL);
813 810
814 811 if (dir_name[0][0] == '\0') {
815 812 /*
816 813 * construct the module directory names
817 814 */
818 815 if (sysinfo(SI_PLATFORM, infobuf, MAXPATHLEN) == -1) {
819 816 dprintf((stderr, "sysinfo %s\n", strerror(errno)));
820 817 return (NULL);
821 818 } else {
822 819 if (snprintf(dir_name[0], MAXPATHLEN, MODULE_DIR_HW,
823 820 infobuf) >= MAXPATHLEN ||
824 821 snprintf(dir_name[N_MODULE_DIR + 1], MAXPATHLEN,
825 822 SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) {
826 823 dprintf((stderr,
827 824 "invalid module or script directory for "
828 825 "platform %s\n", infobuf));
829 826 return (NULL);
830 827 }
831 828 }
832 829
833 830 if (sysinfo(SI_MACHINE, infobuf, MAXPATHLEN) == -1) {
834 831 dprintf((stderr, "sysinfo %s\n", strerror(errno)));
835 832 return (NULL);
836 833 } else {
837 834 if (snprintf(dir_name[1], MAXPATHLEN, MODULE_DIR_HW,
838 835 infobuf) >= MAXPATHLEN ||
839 836 snprintf(dir_name[N_MODULE_DIR + 2], MAXPATHLEN,
840 837 SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) {
841 838 dprintf((stderr,
842 839 "invalid module or script directory for "
843 840 "machine type %s\n", infobuf));
844 841 return (NULL);
845 842 }
846 843 }
847 844
848 845 if (strlcpy(dir_name[2], MODULE_DIR_GEN, MAXPATHLEN) >=
849 846 MAXPATHLEN ||
850 847 strlcpy(dir_name[N_MODULE_DIR + 3], SCRIPT_DIR_GEN,
851 848 MAXPATHLEN) >= MAXPATHLEN ||
852 849 strlcpy(dir_name[N_MODULE_DIR + 0], SCRIPT_DIR_ETC,
853 850 MAXPATHLEN) >= MAXPATHLEN) {
854 851 dprintf((stderr,
855 852 "invalid module or script generic directory\n"));
856 853 return (NULL);
857 854 }
858 855 }
859 856
860 857 if (rcm_script)
861 858 *rcm_script = (dirnum < N_MODULE_DIR) ? 0 : 1;
862 859
863 860 return (dir_name[dirnum]);
864 861 }
865 862
866 863 /*
867 864 * Find the directory where the script is located.
868 865 * If the script is found return a pointer to the directory where the
869 866 * script was found otherwise return NULL.
870 867 */
871 868 char *
872 869 rcm_get_script_dir(char *script_name)
873 870 {
874 871 uint_t i;
875 872 char *dir_name;
876 873 char path[MAXPATHLEN];
877 874 struct stat stats;
878 875
879 876 for (i = 0; (dir_name = rcm_script_dir(i)) != NULL; i++) {
880 877 if (snprintf(path, MAXPATHLEN, "%s%s", dir_name, script_name)
881 878 >= MAXPATHLEN) {
882 879 dprintf((stderr, "invalid script %s skipped\n",
883 880 script_name));
884 881 continue;
885 882 }
886 883 if (stat(path, &stats) == 0)
887 884 return (dir_name);
888 885 }
889 886
890 887 return (NULL);
891 888 }
892 889
893 890 /*
894 891 * Returns 1 if the filename is an rcm script.
895 892 * Returns 0 if the filename is an rcm module.
896 893 */
897 894 int
898 895 rcm_is_script(char *filename)
899 896 {
900 897 char *tmp;
901 898
902 899 if (((tmp = strstr(filename, RCM_MODULE_SUFFIX)) != NULL) &&
903 900 (tmp[strlen(RCM_MODULE_SUFFIX)] == '\0'))
904 901 return (0);
905 902 else
906 903 return (1);
907 904 }
908 905
909 906 /* Locate the module and call dlopen */
910 907 void *
911 908 rcm_module_open(char *modname)
912 909 {
913 910 unsigned i;
914 911 char *dir_name;
915 912 void *dlhandle = NULL;
916 913 char modpath[MAXPATHLEN];
917 914
918 915 #ifdef DEBUG
919 916 struct stat sbuf;
920 917 #endif
921 918
922 919 /*
923 920 * dlopen the module
924 921 */
925 922 for (i = 0; (dir_name = rcm_module_dir(i)) != NULL; i++) {
926 923 if (snprintf(modpath, MAXPATHLEN, "%s%s", dir_name, modname)
927 924 >= MAXPATHLEN) {
928 925 dprintf((stderr, "invalid module %s skipped\n",
929 926 modname));
930 927 continue;
931 928 }
932 929
933 930 if ((dlhandle = dlopen(modpath, RTLD_LAZY)) != NULL) {
934 931 return (dlhandle);
935 932 }
936 933
937 934 dprintf((stderr, "failure (dlopen=%s)\n", dlerror()));
938 935 #ifdef DEBUG
939 936 if (stat(modpath, &sbuf) == 0) {
940 937 (void) fprintf(stderr, "%s is not a valid module\n",
941 938 modpath);
942 939 }
943 940 #endif
944 941 }
945 942
946 943 dprintf((stderr, "module %s not found\n", modname));
947 944 return (NULL);
948 945 }
949 946
950 947 /* dlclose module */
951 948 void
952 949 rcm_module_close(void *dlhandle)
953 950 {
954 951 if (dlclose(dlhandle) == 0)
955 952 return;
956 953
957 954 dprintf((stderr, "dlclose: %s\n", dlerror()));
958 955 }
959 956
960 957
961 958 /*
962 959 * stub implementation of rcm_log_message allows dlopen of rcm modules
963 960 * to proceed in absence of rcm_daemon.
964 961 *
965 962 * This definition is interposed by the definition in rcm_daemon because of the
966 963 * default search order implemented by the linker and dlsym(). All RCM modules
967 964 * will see the daemon version when loaded by the rcm_daemon.
968 965 */
969 966 /* ARGSUSED */
970 967 void
971 968 rcm_log_message(int level, char *message, ...)
972 969 {
973 970 dprintf((stderr, "rcm_log_message stub\n"));
974 971 }
975 972
976 973 /*
977 974 * Helper functions
978 975 */
979 976
980 977 /*
981 978 * Common routine for all rcm calls which require daemon processing
982 979 */
983 980 static int
984 981 rcm_common(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, void *arg,
985 982 rcm_info_t **infop)
986 983 {
987 984 int i;
988 985
989 986 if (hd == NULL) {
990 987 errno = EINVAL;
991 988 return (RCM_FAILURE);
992 989 }
993 990
994 991 if (getuid() != 0) {
995 992 errno = EPERM;
996 993 return (RCM_FAILURE);
997 994 }
998 995
999 996 if ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0) {
1000 997 if ((rsrcnames == NULL) || (rsrcnames[0] == NULL)) {
1001 998 errno = EINVAL;
1002 999 return (RCM_FAILURE);
1003 1000 }
1004 1001
1005 1002 for (i = 0; rsrcnames[i] != NULL; i++) {
1006 1003 if (*rsrcnames[i] == '\0') {
1007 1004 errno = EINVAL;
1008 1005 return (RCM_FAILURE);
1009 1006 }
1010 1007 }
1011 1008 }
1012 1009
1013 1010 /*
1014 1011 * Check if handle is allocated by rcm_daemon. If so, this call came
1015 1012 * from an RCM module, so we make a direct call into rcm_daemon.
1016 1013 */
1017 1014 if (hd->lrcm_ops != NULL) {
1018 1015 return (rcm_direct_call(cmd, hd, rsrcnames, flag, arg, infop));
1019 1016 }
1020 1017
1021 1018 /*
1022 1019 * When not called from a RCM module (i.e. no recursion), zero the
1023 1020 * pointer just in case caller did not do so. For recursive calls,
1024 1021 * we want to append rcm_info_t after infop; zero it may cause
1025 1022 * memory leaks.
1026 1023 */
1027 1024 if (infop) {
1028 1025 *infop = NULL;
1029 1026 }
1030 1027
1031 1028 /*
1032 1029 * Now call into the daemon.
1033 1030 */
1034 1031 return (rcm_daemon_call(cmd, hd, rsrcnames, flag, arg, infop));
1035 1032 }
1036 1033
1037 1034 /*
1038 1035 * Caller is an RCM module, call directly into rcm_daemon.
1039 1036 */
1040 1037 static int
1041 1038 rcm_direct_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag,
1042 1039 void *arg, rcm_info_t **infop)
1043 1040 {
1044 1041 int error;
1045 1042
1046 1043 librcm_ops_t *ops = (librcm_ops_t *)hd->lrcm_ops;
1047 1044 switch (cmd) {
1048 1045 case CMD_GETINFO:
1049 1046 error = ops->librcm_getinfo(rsrcnames, flag, hd->seq_num,
1050 1047 infop);
1051 1048 break;
1052 1049
1053 1050 case CMD_OFFLINE:
1054 1051 error = ops->librcm_offline(rsrcnames, hd->pid, flag,
1055 1052 hd->seq_num, infop);
1056 1053 break;
1057 1054
1058 1055 case CMD_ONLINE:
1059 1056 error = ops->librcm_online(rsrcnames, hd->pid, flag,
1060 1057 hd->seq_num, infop);
1061 1058 break;
1062 1059
1063 1060 case CMD_REMOVE:
1064 1061 error = ops->librcm_remove(rsrcnames, hd->pid, flag,
1065 1062 hd->seq_num, infop);
1066 1063 break;
1067 1064
1068 1065 case CMD_SUSPEND:
1069 1066 error = ops->librcm_suspend(rsrcnames, hd->pid, flag,
1070 1067 hd->seq_num, (timespec_t *)arg, infop);
1071 1068 break;
1072 1069
1073 1070 case CMD_RESUME:
1074 1071 error = ops->librcm_resume(rsrcnames, hd->pid, flag,
1075 1072 hd->seq_num, infop);
1076 1073 break;
1077 1074
1078 1075 case CMD_REGISTER:
1079 1076 error = ops->librcm_regis(hd->modname, rsrcnames[0], hd->pid,
1080 1077 flag, infop);
1081 1078 break;
1082 1079
1083 1080 case CMD_UNREGISTER:
1084 1081 error = ops->librcm_unregis(hd->modname, rsrcnames[0], hd->pid,
1085 1082 flag);
1086 1083 break;
1087 1084
1088 1085 case CMD_REQUEST_CHANGE:
1089 1086 error = ops->librcm_request_change(rsrcnames[0], hd->pid, flag,
1090 1087 hd->seq_num, (nvlist_t *)arg, infop);
1091 1088 break;
1092 1089
1093 1090 case CMD_NOTIFY_CHANGE:
1094 1091 error = ops->librcm_notify_change(rsrcnames[0], hd->pid, flag,
1095 1092 hd->seq_num, (nvlist_t *)arg, infop);
1096 1093 break;
1097 1094
1098 1095 case CMD_EVENT:
1099 1096 error = ops->librcm_notify_event(rsrcnames[0], hd->pid, flag,
1100 1097 hd->seq_num, (nvlist_t *)arg, infop);
1101 1098 break;
1102 1099
1103 1100 case CMD_GETSTATE:
1104 1101 error = ops->librcm_getstate(rsrcnames[0], hd->pid, infop);
1105 1102 break;
1106 1103
1107 1104 default:
1108 1105 dprintf((stderr, "invalid command: %d\n", cmd));
1109 1106 error = EFAULT;
1110 1107 }
1111 1108
1112 1109 if (error > 0) {
1113 1110 errno = error;
1114 1111 error = RCM_FAILURE;
1115 1112 }
1116 1113 return (error);
1117 1114 }
1118 1115
1119 1116 /*
1120 1117 * Call into rcm_daemon door to process the request
1121 1118 */
1122 1119 static int
1123 1120 rcm_daemon_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag,
1124 1121 void *arg, rcm_info_t **infop)
1125 1122 {
1126 1123 int errno_found;
1127 1124 int daemon_errno = 0;
1128 1125 int error = RCM_SUCCESS;
1129 1126 int delay = 300;
1130 1127 int maxdelay = 10000; /* 10 seconds */
1131 1128 char *nvl_packed = NULL;
1132 1129 size_t nvl_size = 0;
1133 1130 nvlist_t *ret = NULL;
1134 1131 nvpair_t *nvp;
1135 1132 size_t rsize = 0;
1136 1133 rcm_info_t *info = NULL;
1137 1134
1138 1135 errno = 0;
1139 1136
1140 1137 /*
1141 1138 * Decide whether to start the daemon
1142 1139 */
1143 1140 switch (cmd) {
1144 1141 case CMD_GETINFO:
1145 1142 case CMD_OFFLINE:
1146 1143 case CMD_ONLINE:
1147 1144 case CMD_REMOVE:
1148 1145 case CMD_SUSPEND:
1149 1146 case CMD_RESUME:
1150 1147 case CMD_REGISTER:
1151 1148 case CMD_UNREGISTER:
1152 1149 case CMD_EVENT:
1153 1150 case CMD_REQUEST_CHANGE:
1154 1151 case CMD_NOTIFY_CHANGE:
1155 1152 case CMD_GETSTATE:
1156 1153 break;
1157 1154
1158 1155 default:
1159 1156 errno = EFAULT;
1160 1157 return (RCM_FAILURE);
1161 1158 }
1162 1159
1163 1160 if (rcm_daemon_is_alive() != 1) {
1164 1161 dprintf((stderr, "failed to start rcm_daemon\n"));
1165 1162 errno = EFAULT;
1166 1163 return (RCM_FAILURE);
1167 1164 }
1168 1165
1169 1166 /*
1170 1167 * Generate a packed nvlist for the request
1171 1168 */
1172 1169 if (rcm_generate_nvlist(cmd, hd, rsrcnames, flag, arg, &nvl_packed,
1173 1170 &nvl_size) < 0) {
1174 1171 dprintf((stderr, "error in nvlist generation\n"));
1175 1172 errno = EFAULT;
1176 1173 return (RCM_FAILURE);
1177 1174 }
1178 1175
1179 1176 /*
1180 1177 * Make the door call and get a return event. We go into a retry loop
1181 1178 * when RCM_ET_EAGAIN is returned.
1182 1179 */
1183 1180 retry:
1184 1181 if (get_event_service(RCM_SERVICE_DOOR, (void *)nvl_packed, nvl_size,
1185 1182 (void **)&ret, &rsize) < 0) {
1186 1183 dprintf((stderr, "rcm_daemon call failed: %s\n",
1187 1184 strerror(errno)));
1188 1185 free(nvl_packed);
1189 1186 return (RCM_FAILURE);
1190 1187 }
1191 1188
1192 1189 assert(ret != NULL);
1193 1190
1194 1191 /*
1195 1192 * nvlist_lookup_* routines don't work because the returned nvlist
1196 1193 * was nvlist_alloc'ed without the NV_UNIQUE_NAME flag. Implement
1197 1194 * a sequential search manually, which is fine since there is only
1198 1195 * one RCM_RESULT value in the nvlist.
1199 1196 */
1200 1197 errno_found = 0;
1201 1198 nvp = NULL;
1202 1199 while (nvp = nvlist_next_nvpair(ret, nvp)) {
1203 1200 if (strcmp(nvpair_name(nvp), RCM_RESULT) == 0) {
1204 1201 if (errno = nvpair_value_int32(nvp, &daemon_errno)) {
1205 1202 error = RCM_FAILURE;
1206 1203 goto out;
1207 1204 }
1208 1205 errno_found++;
1209 1206 break;
1210 1207 }
1211 1208 }
1212 1209 if (errno_found == 0) {
1213 1210 errno = EFAULT;
1214 1211 error = RCM_FAILURE;
1215 1212 goto out;
1216 1213 }
1217 1214
1218 1215 if (daemon_errno == EAGAIN) {
1219 1216 /*
1220 1217 * Wait and retry
1221 1218 */
1222 1219 dprintf((stderr, "retry door_call\n"));
1223 1220
1224 1221 if (delay > maxdelay) {
1225 1222 errno = EAGAIN;
1226 1223 error = RCM_FAILURE;
1227 1224 goto out;
1228 1225 }
1229 1226
1230 1227 (void) poll(NULL, 0, delay);
1231 1228 delay *= 2; /* exponential back off */
1232 1229 nvlist_free(ret);
1233 1230 goto retry;
1234 1231 }
1235 1232
1236 1233 /*
1237 1234 * The door call succeeded. Now extract info from returned event.
1238 1235 */
1239 1236 if (extract_info(ret, &info) != 0) {
1240 1237 dprintf((stderr, "error in extracting event data\n"));
1241 1238 errno = EFAULT;
1242 1239 error = RCM_FAILURE;
1243 1240 goto out;
1244 1241 }
1245 1242
1246 1243 if (infop)
1247 1244 *infop = info;
1248 1245 else
1249 1246 rcm_free_info(info);
1250 1247
1251 1248 if (daemon_errno) {
1252 1249 if (daemon_errno > 0) {
↓ open down ↓ |
693 lines elided |
↑ open up ↑ |
1253 1250 errno = daemon_errno;
1254 1251 error = RCM_FAILURE;
1255 1252 } else {
1256 1253 error = daemon_errno;
1257 1254 }
1258 1255 }
1259 1256
1260 1257 out:
1261 1258 if (nvl_packed)
1262 1259 free(nvl_packed);
1263 - if (ret)
1264 - nvlist_free(ret);
1260 + nvlist_free(ret);
1265 1261 dprintf((stderr, "daemon call is done. error = %d, errno = %s\n", error,
1266 1262 strerror(errno)));
1267 1263 return (error);
1268 1264 }
1269 1265
1270 1266 /*
1271 1267 * Extract registration info from event data.
1272 1268 * Return 0 on success and -1 on failure.
1273 1269 */
1274 1270 static int
1275 1271 extract_info(nvlist_t *nvl, rcm_info_t **infop)
1276 1272 {
1277 1273 rcm_info_t *info = NULL;
1278 1274 rcm_info_t *prev = NULL;
1279 1275 rcm_info_t *tmp = NULL;
1280 1276 char *buf;
1281 1277 uint_t buflen;
1282 1278 nvpair_t *nvp = NULL;
1283 1279
1284 1280 while (nvp = nvlist_next_nvpair(nvl, nvp)) {
1285 1281
1286 1282 buf = NULL;
1287 1283 buflen = 0;
1288 1284
1289 1285 if (strcmp(nvpair_name(nvp), RCM_RESULT_INFO) != 0)
1290 1286 continue;
1291 1287
1292 1288 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
1293 1289 dprintf((stderr, "out of memory\n"));
1294 1290 goto fail;
1295 1291 }
1296 1292
1297 1293 if (errno = nvpair_value_byte_array(nvp, (uchar_t **)&buf,
1298 1294 &buflen)) {
1299 1295 free(tmp);
1300 1296 dprintf((stderr, "failed (nvpair_value=%s)\n",
1301 1297 strerror(errno)));
1302 1298 goto fail;
1303 1299 }
1304 1300 if (errno = nvlist_unpack(buf, buflen, &(tmp->info), 0)) {
1305 1301 free(tmp);
1306 1302 dprintf((stderr, "failed (nvlist_unpack=%s)\n",
1307 1303 strerror(errno)));
1308 1304 goto fail;
1309 1305 }
1310 1306
1311 1307 if (info == NULL) {
1312 1308 prev = info = tmp;
1313 1309 } else {
1314 1310 prev->next = tmp;
1315 1311 prev = tmp;
1316 1312 }
1317 1313 }
1318 1314
1319 1315 *infop = info;
1320 1316 return (0);
1321 1317
1322 1318 fail:
1323 1319 rcm_free_info(info);
1324 1320 *infop = NULL;
1325 1321 return (-1);
1326 1322 }
1327 1323
1328 1324 /* Generate a packed nvlist for communicating with RCM daemon */
1329 1325 static int
1330 1326 rcm_generate_nvlist(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag,
1331 1327 void *arg, char **nvl_packed, size_t *nvl_size)
1332 1328 {
1333 1329 int nrsrcnames;
1334 1330 char *buf = NULL;
1335 1331 size_t buflen = 0;
1336 1332 nvlist_t *nvl = NULL;
1337 1333
1338 1334 assert((nvl_packed != NULL) && (nvl_size != NULL));
1339 1335
1340 1336 *nvl_size = 0;
1341 1337 *nvl_packed = NULL;
1342 1338
1343 1339 /* Allocate an empty nvlist */
1344 1340 if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) > 0) {
1345 1341 dprintf((stderr, "failed (nvlist_alloc=%s).\n",
1346 1342 strerror(errno)));
1347 1343 return (-1);
1348 1344 }
1349 1345
1350 1346 /* Stuff in all the arguments for the daemon call */
1351 1347 if (nvlist_add_int32(nvl, RCM_CMD, cmd) != 0) {
1352 1348 dprintf((stderr, "failed (nvlist_add(CMD)=%s).\n",
1353 1349 strerror(errno)));
1354 1350 goto fail;
1355 1351 }
1356 1352 if (rsrcnames) {
1357 1353 nrsrcnames = 0;
1358 1354 while (rsrcnames[nrsrcnames] != NULL)
1359 1355 nrsrcnames++;
1360 1356 if (nvlist_add_string_array(nvl, RCM_RSRCNAMES, rsrcnames,
1361 1357 nrsrcnames) != 0) {
1362 1358 dprintf((stderr, "failed (nvlist_add(RSRCNAMES)=%s).\n",
1363 1359 strerror(errno)));
1364 1360 goto fail;
1365 1361 }
1366 1362 }
1367 1363 if (hd->modname) {
1368 1364 if (nvlist_add_string(nvl, RCM_CLIENT_MODNAME, hd->modname)
1369 1365 != 0) {
1370 1366 dprintf((stderr,
1371 1367 "failed (nvlist_add(CLIENT_MODNAME)=%s).\n",
1372 1368 strerror(errno)));
1373 1369 goto fail;
1374 1370 }
1375 1371 }
1376 1372 if (hd->pid) {
1377 1373 if (nvlist_add_uint64(nvl, RCM_CLIENT_ID, hd->pid) != 0) {
1378 1374 dprintf((stderr, "failed (nvlist_add(CLIENT_ID)=%s).\n",
1379 1375 strerror(errno)));
1380 1376 goto fail;
1381 1377 }
1382 1378 }
1383 1379 if (flag) {
1384 1380 if (nvlist_add_uint32(nvl, RCM_REQUEST_FLAG, flag) != 0) {
1385 1381 dprintf((stderr,
1386 1382 "failed (nvlist_add(REQUEST_FLAG)=%s).\n",
1387 1383 strerror(errno)));
1388 1384 goto fail;
1389 1385 }
1390 1386 }
1391 1387 if (arg && cmd == CMD_SUSPEND) {
1392 1388 if (nvlist_add_byte_array(nvl, RCM_SUSPEND_INTERVAL,
1393 1389 (uchar_t *)arg, sizeof (timespec_t)) != 0) {
1394 1390 dprintf((stderr,
1395 1391 "failed (nvlist_add(SUSPEND_INTERVAL)=%s).\n",
1396 1392 strerror(errno)));
1397 1393 goto fail;
1398 1394 }
1399 1395 }
1400 1396 if (arg &&
1401 1397 ((cmd == CMD_REQUEST_CHANGE) || (cmd == CMD_NOTIFY_CHANGE))) {
1402 1398 if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE,
1403 1399 0)) {
1404 1400 dprintf((stderr,
1405 1401 "failed (nvlist_pack(CHANGE_DATA)=%s).\n",
1406 1402 strerror(errno)));
1407 1403 goto fail;
1408 1404 }
1409 1405 if (nvlist_add_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t *)buf,
1410 1406 buflen) != 0) {
1411 1407 dprintf((stderr,
1412 1408 "failed (nvlist_add(CHANGE_DATA)=%s).\n",
1413 1409 strerror(errno)));
1414 1410 goto fail;
1415 1411 }
1416 1412 }
1417 1413 if (arg && cmd == CMD_EVENT) {
1418 1414 if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE,
1419 1415 0)) {
1420 1416 dprintf((stderr,
1421 1417 "failed (nvlist_pack(CHANGE_DATA)=%s).\n",
1422 1418 strerror(errno)));
1423 1419 goto fail;
1424 1420 }
1425 1421 if (nvlist_add_byte_array(nvl, RCM_EVENT_DATA, (uchar_t *)buf,
1426 1422 buflen) != 0) {
1427 1423 dprintf((stderr,
1428 1424 "failed (nvlist_add(EVENT_DATA)=%s).\n",
1429 1425 strerror(errno)));
1430 1426 goto fail;
1431 1427 }
1432 1428 }
1433 1429
1434 1430 /* Pack the nvlist */
1435 1431 if (errno = nvlist_pack(nvl, nvl_packed, nvl_size, NV_ENCODE_NATIVE,
1436 1432 0)) {
1437 1433 dprintf((stderr, "failed (nvlist_pack=%s).\n",
1438 1434 strerror(errno)));
1439 1435 goto fail;
1440 1436 }
1441 1437
1442 1438 /* If an argument was packed intermediately, free the buffer */
↓ open down ↓ |
168 lines elided |
↑ open up ↑ |
1443 1439 if (buf)
1444 1440 free(buf);
1445 1441
1446 1442 /* Free the unpacked version of the nvlist and return the packed list */
1447 1443 nvlist_free(nvl);
1448 1444 return (0);
1449 1445
1450 1446 fail:
1451 1447 if (buf)
1452 1448 free(buf);
1453 - if (nvl)
1454 - nvlist_free(nvl);
1449 + nvlist_free(nvl);
1455 1450 if (*nvl_packed)
1456 1451 free(*nvl_packed);
1457 1452 *nvl_packed = NULL;
1458 1453 *nvl_size = 0;
1459 1454 return (-1);
1460 1455 }
1461 1456
1462 1457 /* check if rcm_daemon is up and running */
1463 1458 static int
1464 1459 rcm_daemon_is_alive()
1465 1460 {
1466 1461 int lasttry;
1467 1462 struct stat st;
1468 1463 nvlist_t *nvl;
1469 1464 char *buf = NULL;
1470 1465 size_t buflen = 0;
1471 1466 int delay = 300;
1472 1467 const int maxdelay = 10000; /* 10 sec */
1473 1468
1474 1469 /* generate a packed nvlist for the door knocking */
1475 1470 if (errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) {
1476 1471 dprintf((stderr, "nvlist_alloc failed: %s\n", strerror(errno)));
1477 1472 return (0);
1478 1473 }
1479 1474 if (errno = nvlist_add_int32(nvl, RCM_CMD, CMD_KNOCK)) {
1480 1475 dprintf((stderr, "nvlist_add failed: %s\n", strerror(errno)));
1481 1476 nvlist_free(nvl);
1482 1477 return (0);
1483 1478 }
1484 1479 if (errno = nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_NATIVE, 0)) {
1485 1480 dprintf((stderr, "nvlist_pack failed: %s\n", strerror(errno)));
1486 1481 nvlist_free(nvl);
1487 1482 return (0);
1488 1483 }
1489 1484 nvlist_free(nvl);
1490 1485
1491 1486 /*
1492 1487 * check the door and knock on it
1493 1488 */
1494 1489 if ((stat(RCM_SERVICE_DOOR, &st) == 0) &&
1495 1490 (get_event_service(RCM_SERVICE_DOOR, (void *)buf, buflen, NULL,
1496 1491 NULL) == 0)) {
1497 1492 free(buf);
1498 1493 return (1); /* daemon is alive */
1499 1494 }
1500 1495
1501 1496 /*
1502 1497 * Attempt to start the daemon.
1503 1498 * If caller has SIGCHLD set to SIG_IGN or its SA_NOCLDWAIT
1504 1499 * flag set, waitpid(2) (hence rcm_exec_cmd) will fail.
1505 1500 * get_event_service will determine if the rcm_daemon started.
1506 1501 */
1507 1502 dprintf((stderr, "exec: %s\n", RCM_DAEMON_START));
1508 1503 (void) rcm_exec_cmd(RCM_DAEMON_START);
1509 1504
1510 1505 /*
1511 1506 * Wait for daemon to respond, timeout at 10 sec
1512 1507 */
1513 1508 while (((lasttry = get_event_service(RCM_SERVICE_DOOR, (void *)buf,
1514 1509 buflen, NULL, NULL)) != 0) &&
1515 1510 ((errno == EBADF) || (errno == ESRCH))) {
1516 1511 if (delay > maxdelay) {
1517 1512 break;
1518 1513 }
1519 1514 (void) poll(NULL, 0, delay);
1520 1515 delay *= 2;
1521 1516 }
1522 1517
1523 1518 free(buf);
1524 1519 if (lasttry == 0)
1525 1520 return (1);
1526 1521 return (0);
1527 1522 }
1528 1523
1529 1524 /*
1530 1525 * Check permission.
1531 1526 *
1532 1527 * The policy is root only for now. Need to relax this when interface level
1533 1528 * is raised.
1534 1529 */
1535 1530 static int
1536 1531 rcm_check_permission(void)
1537 1532 {
1538 1533 return (getuid() == 0);
1539 1534 }
1540 1535
1541 1536 /*
1542 1537 * Project private function - for use by RCM MSTC tests
1543 1538 *
1544 1539 * Get the client name (rcm module name or script name) corresponding to
1545 1540 * the given rcm handle.
1546 1541 */
1547 1542 const char *
1548 1543 rcm_get_client_name(rcm_handle_t *hd)
1549 1544 {
1550 1545 return (hd->modname);
1551 1546 }
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX