Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libscf/common/notify_params.c
+++ new/usr/src/lib/libscf/common/notify_params.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
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 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include "libscf_impl.h"
27 27
28 28 #include <assert.h>
29 29 #include <strings.h>
30 30
31 31 /*
32 32 * Errors returned by smf_notify_{del|get|set}_params()
33 33 */
34 34 static const scf_error_t errs_1[] = {
35 35 SCF_ERROR_BACKEND_ACCESS,
36 36 SCF_ERROR_BACKEND_READONLY,
37 37 SCF_ERROR_CONNECTION_BROKEN,
38 38 SCF_ERROR_DELETED,
39 39 SCF_ERROR_INTERNAL,
40 40 SCF_ERROR_INVALID_ARGUMENT,
41 41 SCF_ERROR_NO_MEMORY,
42 42 SCF_ERROR_NO_RESOURCES,
43 43 SCF_ERROR_NOT_FOUND,
44 44 SCF_ERROR_PERMISSION_DENIED,
45 45 0
46 46 };
47 47
48 48 /*
49 49 * Errors returned by smf_notify_{del|get|set}_params()
50 50 * Except SCF_ERROR_INVALID_ARGUMENT
51 51 */
52 52 static const scf_error_t errs_2[] = {
53 53 SCF_ERROR_BACKEND_ACCESS,
54 54 SCF_ERROR_BACKEND_READONLY,
55 55 SCF_ERROR_CONNECTION_BROKEN,
56 56 SCF_ERROR_DELETED,
57 57 SCF_ERROR_INTERNAL,
58 58 SCF_ERROR_NO_MEMORY,
59 59 SCF_ERROR_NO_RESOURCES,
60 60 SCF_ERROR_NOT_FOUND,
61 61 SCF_ERROR_PERMISSION_DENIED,
62 62 0
63 63 };
64 64
65 65 /*
66 66 * Helper function that abort() on unexpected errors.
67 67 * The expected error set is a zero-terminated array of scf_error_t
68 68 */
69 69 static int
70 70 check_scf_error(scf_error_t e, const scf_error_t *errs)
71 71 {
72 72 if (ismember(e, errs))
73 73 return (1);
74 74
75 75 assert(0);
76 76 abort();
77 77
78 78 /*NOTREACHED*/
79 79 }
80 80
81 81 /*
82 82 * Mapping of state transition to pgname.
83 83 */
84 84 static struct st_pgname {
85 85 const char *st_pgname;
86 86 int32_t st_state;
87 87 } st_pgnames[] = {
88 88 { "to-uninitialized", SCF_TRANS(0, SCF_STATE_UNINIT) },
89 89 { "from-uninitialized", SCF_TRANS(SCF_STATE_UNINIT, 0) },
90 90 { "to-maintenance", SCF_TRANS(0, SCF_STATE_MAINT) },
91 91 { "from-maintenance", SCF_TRANS(SCF_STATE_MAINT, 0) },
92 92 { "to-offline", SCF_TRANS(0, SCF_STATE_OFFLINE) },
93 93 { "from-offline", SCF_TRANS(SCF_STATE_OFFLINE, 0) },
94 94 { "to-disabled", SCF_TRANS(0, SCF_STATE_DISABLED) },
95 95 { "from-disabled", SCF_TRANS(SCF_STATE_DISABLED, 0) },
96 96 { "to-online", SCF_TRANS(0, SCF_STATE_ONLINE) },
97 97 { "from-online", SCF_TRANS(SCF_STATE_ONLINE, 0) },
98 98 { "to-degraded", SCF_TRANS(0, SCF_STATE_DEGRADED) },
99 99 { "from-degraded", SCF_TRANS(SCF_STATE_DEGRADED, 0) },
100 100 { NULL, 0 }
101 101 };
102 102
103 103 /*
104 104 * Check if class matches or is a subclass of SCF_SVC_TRANSITION_CLASS
105 105 *
106 106 * returns 1, otherwise return 0
107 107 */
108 108 static boolean_t
109 109 is_svc_stn(const char *class)
110 110 {
111 111 int n = strlen(SCF_SVC_TRANSITION_CLASS);
112 112
113 113 if (class && strncmp(class, SCF_SVC_TRANSITION_CLASS, n) == 0)
114 114 if (class[n] == '\0' || class[n] == '.')
115 115 return (1);
116 116 return (0);
117 117 }
118 118
119 119 /*
120 120 * Return the len of the base class. For instance, "class.class1.class2.*"
121 121 * will return the length of "class.class1.class2"
122 122 * This function does not check if the class or base class is valid.
123 123 * A class such as "class.class1....****" is not valid but will return the
124 124 * length of "class.class1....***"
125 125 */
126 126 static size_t
127 127 base_class_len(const char *c)
128 128 {
129 129 const char *p;
130 130 size_t n;
131 131
132 132 if ((n = strlen(c)) == 0)
133 133 return (0);
134 134
135 135 p = c + n;
136 136
137 137 /* get rid of any trailing asterisk */
138 138 if (*--p == '*')
139 139 n--;
140 140
141 141 /* make sure the class doesn't end in '.' */
142 142 while (p >= c && *--p == '.')
143 143 n--;
144 144
145 145 return (n);
146 146 }
147 147
148 148 /*
149 149 * Allocates and builds the pgname for an FMA dotted class.
150 150 * The pgname will be of the form "class.class1.class2,SCF_NOTIFY_PG_POSTFIX"
151 151 *
152 152 * NULL on error
153 153 */
154 154 static char *
155 155 class_to_pgname(const char *class)
156 156 {
157 157 size_t n;
158 158 ssize_t sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
159 159 char *pgname = NULL;
160 160
161 161 n = base_class_len(class);
162 162
163 163 if (n == 0) {
164 164 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
165 165 return (NULL);
166 166 }
167 167
168 168 if ((pgname = malloc(sz)) == NULL) {
169 169 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
170 170 goto error;
171 171 }
172 172
173 173 if (snprintf(pgname, sz, "%.*s,%s", (int)n, class,
174 174 SCF_NOTIFY_PG_POSTFIX) >= sz) {
175 175 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
176 176 goto error;
177 177 }
178 178 return (pgname);
179 179
180 180 error:
181 181 free(pgname);
182 182 pgname = NULL;
183 183
184 184 return (pgname);
185 185 }
186 186
187 187 /*
188 188 * Get the pg from the running snapshot of the instance (composed or not)
189 189 */
190 190 static int
191 191 get_pg(scf_service_t *s, scf_instance_t *i, const char *n,
192 192 scf_propertygroup_t *pg, int composed)
193 193 {
194 194 scf_handle_t *h = scf_instance_handle(i);
195 195 scf_error_t scf_e = scf_error();
196 196 scf_snapshot_t *snap = scf_snapshot_create(h);
197 197 scf_snaplevel_t *slvl = scf_snaplevel_create(h);
198 198 int r = -1;
199 199
200 200 if (h == NULL) {
201 201 /*
202 202 * Use the error stored in scf_e
203 203 */
204 204 (void) scf_set_error(scf_e);
205 205 goto out;
206 206 }
207 207 if (s == NULL) {
208 208 if (snap == NULL || slvl == NULL)
209 209 goto out;
210 210 if (scf_instance_get_snapshot(i, "running", snap) != 0)
211 211 goto out;
212 212
213 213 if (composed) {
214 214 if (scf_instance_get_pg_composed(i, snap, n, pg) != 0)
215 215 goto out;
216 216 } else {
217 217 if (scf_snapshot_get_base_snaplevel(snap, slvl) != 0 ||
218 218 scf_snaplevel_get_pg(slvl, n, pg) != 0)
219 219 goto out;
220 220 }
221 221 } else {
222 222 if (scf_service_get_pg(s, n, pg) != 0)
223 223 goto out;
224 224 }
225 225
226 226 r = 0;
227 227 out:
228 228 scf_snaplevel_destroy(slvl);
229 229 scf_snapshot_destroy(snap);
230 230
231 231 return (r);
232 232 }
233 233
234 234 /*
235 235 * Add a pg if it does not exist, or get it if it exists.
236 236 * It operates on the instance if the service parameter is NULL.
237 237 *
238 238 * returns 0 on success or -1 on failure
239 239 */
240 240 static int
241 241 get_or_add_pg(scf_service_t *s, scf_instance_t *i, const char *n, const char *t,
242 242 uint32_t flags, scf_propertygroup_t *pg)
243 243 {
244 244 int r;
245 245
246 246 if (s == NULL)
247 247 r = scf_instance_add_pg(i, n, t, flags, pg);
248 248 else
249 249 r = scf_service_add_pg(s, n, t, flags, pg);
250 250
251 251 if (r == 0)
252 252 return (0);
253 253 else if (scf_error() != SCF_ERROR_EXISTS)
254 254 return (-1);
255 255
256 256 if (s == NULL)
257 257 r = scf_instance_get_pg(i, n, pg);
258 258 else
259 259 r = scf_service_get_pg(s, n, pg);
260 260
261 261 return (r);
262 262 }
263 263
264 264 /*
265 265 * Delete the property group form the instance or service.
266 266 * If service is NULL, use instance, otherwise use only the service.
267 267 *
268 268 * Return SCF_SUCCESS or SCF_FAILED on
269 269 * SCF_ERROR_BACKEND_ACCESS
270 270 * SCF_ERROR_BACKEND_READONLY
271 271 * SCF_ERROR_CONNECTION_BROKEN
272 272 * SCF_ERROR_DELETED
273 273 * SCF_ERROR_HANDLE_MISMATCH
274 274 * SCF_ERROR_INTERNAL
275 275 * SCF_ERROR_INVALID_ARGUMENT
276 276 * SCF_ERROR_NO_RESOURCES
277 277 * SCF_ERROR_NOT_BOUND
278 278 * SCF_ERROR_NOT_FOUND
279 279 * SCF_ERROR_NOT_SET
280 280 * SCF_ERROR_PERMISSION_DENIED
281 281 */
282 282 static int
283 283 del_pg(scf_service_t *s, scf_instance_t *i, const char *n,
284 284 scf_propertygroup_t *pg)
285 285 {
286 286 if ((s == NULL ? scf_instance_get_pg(i, n, pg) :
287 287 scf_service_get_pg(s, n, pg)) != SCF_SUCCESS)
288 288 if (scf_error() == SCF_ERROR_NOT_FOUND)
289 289 return (SCF_SUCCESS);
290 290 else
291 291 return (SCF_FAILED);
292 292
293 293 if (scf_pg_delete(pg) != SCF_SUCCESS)
294 294 if (scf_error() == SCF_ERROR_DELETED)
295 295 return (SCF_SUCCESS);
296 296 else
297 297 return (SCF_FAILED);
298 298
299 299 return (SCF_SUCCESS);
300 300 }
301 301
302 302 static scf_type_t
303 303 get_scf_type(nvpair_t *p)
304 304 {
305 305 switch (nvpair_type(p)) {
306 306 case DATA_TYPE_BOOLEAN:
307 307 case DATA_TYPE_BOOLEAN_VALUE:
308 308 case DATA_TYPE_BOOLEAN_ARRAY:
309 309 return (SCF_TYPE_BOOLEAN);
310 310
311 311 case DATA_TYPE_BYTE:
312 312 case DATA_TYPE_UINT8:
313 313 case DATA_TYPE_UINT16:
314 314 case DATA_TYPE_UINT32:
315 315 case DATA_TYPE_UINT64:
316 316 case DATA_TYPE_BYTE_ARRAY:
317 317 case DATA_TYPE_UINT8_ARRAY:
318 318 case DATA_TYPE_UINT16_ARRAY:
319 319 case DATA_TYPE_UINT32_ARRAY:
320 320 case DATA_TYPE_UINT64_ARRAY:
321 321 return (SCF_TYPE_COUNT);
322 322
323 323 case DATA_TYPE_INT8:
324 324 case DATA_TYPE_INT16:
325 325 case DATA_TYPE_INT32:
326 326 case DATA_TYPE_INT64:
327 327 case DATA_TYPE_INT8_ARRAY:
328 328 case DATA_TYPE_INT16_ARRAY:
329 329 case DATA_TYPE_INT32_ARRAY:
330 330 case DATA_TYPE_INT64_ARRAY:
331 331 return (SCF_TYPE_INTEGER);
332 332
333 333 case DATA_TYPE_STRING:
334 334 case DATA_TYPE_STRING_ARRAY:
335 335 return (SCF_TYPE_ASTRING);
336 336
337 337 default:
338 338 return (SCF_TYPE_INVALID);
339 339 }
340 340 }
341 341
342 342 static int
343 343 add_entry(scf_transaction_entry_t *te, scf_value_t *val)
344 344 {
345 345 if (scf_entry_add_value(te, val) != 0) {
346 346 scf_value_destroy(val);
347 347 return (SCF_FAILED);
348 348 }
349 349
350 350 return (SCF_SUCCESS);
351 351 }
352 352
353 353 static int
354 354 add_boolean_entry(scf_handle_t *h, scf_transaction_entry_t *te, uint8_t v)
355 355 {
356 356 scf_value_t *val = scf_value_create(h);
357 357
358 358 if (val == NULL)
359 359 return (SCF_FAILED);
360 360
361 361 scf_value_set_boolean(val, v);
362 362
363 363 return (add_entry(te, val));
364 364 }
365 365
366 366 static int
367 367 add_count_entry(scf_handle_t *h, scf_transaction_entry_t *te, uint64_t v)
368 368 {
369 369 scf_value_t *val = scf_value_create(h);
370 370
371 371 if (val == NULL)
372 372 return (SCF_FAILED);
373 373
374 374 scf_value_set_count(val, v);
375 375
376 376 return (add_entry(te, val));
377 377 }
378 378
379 379 static int
380 380 add_integer_entry(scf_handle_t *h, scf_transaction_entry_t *te, int64_t v)
381 381 {
382 382 scf_value_t *val = scf_value_create(h);
383 383
384 384 if (val == NULL)
385 385 return (SCF_FAILED);
386 386
387 387 scf_value_set_integer(val, v);
388 388
389 389 return (add_entry(te, val));
390 390 }
391 391
392 392 static int
393 393 add_astring_entry(scf_handle_t *h, scf_transaction_entry_t *te, char *s)
394 394 {
395 395 scf_value_t *val = scf_value_create(h);
396 396
397 397 if (val == NULL)
398 398 return (SCF_FAILED);
399 399
400 400 if (scf_value_set_astring(val, s) != 0) {
401 401 scf_value_destroy(val);
402 402 return (SCF_FAILED);
403 403 }
404 404
405 405 return (add_entry(te, val));
406 406 }
407 407
408 408 static int
409 409 get_nvpair_vals(scf_handle_t *h, scf_transaction_entry_t *te, nvpair_t *p)
410 410 {
411 411 scf_value_t *val = scf_value_create(h);
412 412 uint_t n = 1;
413 413 int i;
414 414
415 415 if (val == NULL)
416 416 return (SCF_FAILED);
417 417
418 418 switch (nvpair_type(p)) {
419 419 case DATA_TYPE_BOOLEAN:
420 420 return (add_boolean_entry(h, te, 1));
421 421 case DATA_TYPE_BOOLEAN_VALUE:
422 422 {
423 423 boolean_t v;
424 424
425 425 (void) nvpair_value_boolean_value(p, &v);
426 426 return (add_boolean_entry(h, te, (uint8_t)v));
427 427 }
428 428 case DATA_TYPE_BOOLEAN_ARRAY:
429 429 {
430 430 boolean_t *v;
431 431
432 432 (void) nvpair_value_boolean_array(p, &v, &n);
433 433 for (i = 0; i < n; ++i) {
434 434 if (add_boolean_entry(h, te, (uint8_t)v[i]) !=
435 435 SCF_SUCCESS)
436 436 return (SCF_FAILED);
437 437 }
438 438 return (SCF_SUCCESS);
439 439 }
440 440 case DATA_TYPE_BYTE:
441 441 {
442 442 uchar_t v;
443 443
444 444 (void) nvpair_value_byte(p, &v);
445 445 return (add_count_entry(h, te, v));
446 446 }
447 447 case DATA_TYPE_UINT8:
448 448 {
449 449 uint8_t v;
450 450
451 451 (void) nvpair_value_uint8(p, &v);
452 452 return (add_count_entry(h, te, v));
453 453 }
454 454 case DATA_TYPE_UINT16:
455 455 {
456 456 uint16_t v;
457 457
458 458 (void) nvpair_value_uint16(p, &v);
459 459 return (add_count_entry(h, te, v));
460 460 }
461 461 case DATA_TYPE_UINT32:
462 462 {
463 463 uint32_t v;
464 464
465 465 (void) nvpair_value_uint32(p, &v);
466 466 return (add_count_entry(h, te, v));
467 467 }
468 468 case DATA_TYPE_UINT64:
469 469 {
470 470 uint64_t v;
471 471
472 472 (void) nvpair_value_uint64(p, &v);
473 473 return (add_count_entry(h, te, v));
474 474 }
475 475 case DATA_TYPE_BYTE_ARRAY:
476 476 {
477 477 uchar_t *v;
478 478
479 479 (void) nvpair_value_byte_array(p, &v, &n);
480 480 for (i = 0; i < n; ++i) {
481 481 if (add_count_entry(h, te, v[i]) != SCF_SUCCESS)
482 482 return (SCF_FAILED);
483 483 }
484 484 return (SCF_SUCCESS);
485 485 }
486 486 case DATA_TYPE_UINT8_ARRAY:
487 487 {
488 488 uint8_t *v;
489 489
490 490 (void) nvpair_value_uint8_array(p, &v, &n);
491 491 for (i = 0; i < n; ++i) {
492 492 if (add_count_entry(h, te, v[i]) != SCF_SUCCESS)
493 493 return (SCF_FAILED);
494 494 }
495 495 return (SCF_SUCCESS);
496 496 }
497 497 case DATA_TYPE_UINT16_ARRAY:
498 498 {
499 499 uint16_t *v;
500 500
501 501 (void) nvpair_value_uint16_array(p, &v, &n);
502 502 for (i = 0; i < n; ++i) {
503 503 if (add_count_entry(h, te, v[i]) != SCF_SUCCESS)
504 504 return (SCF_FAILED);
505 505 }
506 506 return (SCF_SUCCESS);
507 507 }
508 508 case DATA_TYPE_UINT32_ARRAY:
509 509 {
510 510 uint32_t *v;
511 511
512 512 (void) nvpair_value_uint32_array(p, &v, &n);
513 513 for (i = 0; i < n; ++i) {
514 514 if (add_count_entry(h, te, v[i]) != SCF_SUCCESS)
515 515 return (SCF_FAILED);
516 516 }
517 517 return (SCF_SUCCESS);
518 518 }
519 519 case DATA_TYPE_UINT64_ARRAY:
520 520 {
521 521 uint64_t *v;
522 522
523 523 (void) nvpair_value_uint64_array(p, &v, &n);
524 524 for (i = 0; i < n; ++i) {
525 525 if (add_count_entry(h, te, v[i]) != SCF_SUCCESS)
526 526 return (SCF_FAILED);
527 527 }
528 528 return (SCF_SUCCESS);
529 529 }
530 530 case DATA_TYPE_INT8:
531 531 {
532 532 int8_t v;
533 533
534 534 (void) nvpair_value_int8(p, &v);
535 535 return (add_integer_entry(h, te, v));
536 536 }
537 537 case DATA_TYPE_INT16:
538 538 {
539 539 int16_t v;
540 540
541 541 (void) nvpair_value_int16(p, &v);
542 542 return (add_integer_entry(h, te, v));
543 543 }
544 544 case DATA_TYPE_INT32:
545 545 {
546 546 int32_t v;
547 547
548 548 (void) nvpair_value_int32(p, &v);
549 549 return (add_integer_entry(h, te, v));
550 550 }
551 551 case DATA_TYPE_INT64:
552 552 {
553 553 int64_t v;
554 554
555 555 (void) nvpair_value_int64(p, &v);
556 556 return (add_integer_entry(h, te, v));
557 557 }
558 558 case DATA_TYPE_INT8_ARRAY:
559 559 {
560 560 int8_t *v;
561 561
562 562 (void) nvpair_value_int8_array(p, &v, &n);
563 563 for (i = 0; i < n; ++i) {
564 564 if (add_integer_entry(h, te, v[i]) !=
565 565 SCF_SUCCESS)
566 566 return (SCF_FAILED);
567 567 }
568 568 return (SCF_SUCCESS);
569 569 }
570 570 case DATA_TYPE_INT16_ARRAY:
571 571 {
572 572 int16_t *v;
573 573
574 574 (void) nvpair_value_int16_array(p, &v, &n);
575 575 for (i = 0; i < n; ++i) {
576 576 if (add_integer_entry(h, te, v[i]) !=
577 577 SCF_SUCCESS)
578 578 return (SCF_FAILED);
579 579 }
580 580 return (SCF_SUCCESS);
581 581 }
582 582 case DATA_TYPE_INT32_ARRAY:
583 583 {
584 584 int32_t *v;
585 585
586 586 (void) nvpair_value_int32_array(p, &v, &n);
587 587 for (i = 0; i < n; ++i) {
588 588 if (add_integer_entry(h, te, v[i]) !=
589 589 SCF_SUCCESS)
590 590 return (SCF_FAILED);
591 591 }
592 592 return (SCF_SUCCESS);
593 593 }
594 594 case DATA_TYPE_INT64_ARRAY:
595 595 {
596 596 int64_t *v;
597 597
598 598 (void) nvpair_value_int64_array(p, &v, &n);
599 599 for (i = 0; i < n; ++i) {
600 600 if (add_integer_entry(h, te, v[i]) !=
601 601 SCF_SUCCESS)
602 602 return (SCF_FAILED);
603 603 }
604 604 return (SCF_SUCCESS);
605 605 }
606 606 case DATA_TYPE_STRING:
607 607 {
608 608 char *str;
609 609
610 610 (void) nvpair_value_string(p, &str);
611 611 return (add_astring_entry(h, te, str));
612 612 }
613 613 case DATA_TYPE_STRING_ARRAY:
614 614 {
615 615 char **v;
616 616
617 617 (void) nvpair_value_string_array(p, &v, &n);
618 618 for (i = 0; i < n; ++i) {
619 619 if (add_astring_entry(h, te, v[i]) !=
620 620 SCF_SUCCESS)
621 621 return (SCF_FAILED);
622 622 }
623 623 return (SCF_SUCCESS);
624 624 }
625 625 default:
626 626 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
627 627 return (SCF_FAILED);
628 628 }
629 629
630 630 /*NOTREACHED*/
631 631 }
632 632
633 633 /*
634 634 * Add new transaction entry to scf_transaction_t
635 635 *
636 636 * Can fail with
637 637 * SCF_ERROR_BACKEND_ACCESS
638 638 * SCF_ERROR_CONNECTION_BROKEN
639 639 * SCF_ERROR_DELETED
640 640 * SCF_ERROR_INTERNAL
641 641 * SCF_ERROR_NO_RESOURCES
642 642 * SCF_ERROR_NOT_FOUND
643 643 */
644 644 static int
645 645 prep_transaction(scf_transaction_t *tx, scf_transaction_entry_t *te,
646 646 const char *prop, scf_type_t type)
647 647 {
648 648 if (scf_transaction_property_new(tx, te, prop, type) != SCF_SUCCESS &&
649 649 (scf_error() != SCF_ERROR_EXISTS ||
650 650 scf_transaction_property_change(tx, te, prop, type) !=
651 651 SCF_SUCCESS)) {
652 652 if (check_scf_error(scf_error(), errs_2)) {
653 653 return (SCF_FAILED);
654 654 }
655 655 }
656 656
657 657 return (SCF_SUCCESS);
658 658 }
659 659
660 660 /*
661 661 * notify_set_params()
662 662 * returns 0 on success or -1 on failure
663 663 * SCF_ERROR_BACKEND_ACCESS
664 664 * SCF_ERROR_BACKEND_READONLY
665 665 * SCF_ERROR_CONNECTION_BROKEN
666 666 * SCF_ERROR_DELETED
667 667 * SCF_ERROR_INTERNAL
668 668 * SCF_ERROR_INVALID_ARGUMENT
669 669 * SCF_ERROR_NO_MEMORY
670 670 * SCF_ERROR_NO_RESOURCES
671 671 * SCF_ERROR_NOT_FOUND
672 672 * SCF_ERROR_PERMISSION_DENIED
673 673 */
674 674 static int
675 675 notify_set_params(scf_propertygroup_t *pg, nvlist_t *params)
676 676 {
677 677 scf_handle_t *h = scf_pg_handle(pg);
678 678 scf_error_t scf_e = scf_error();
679 679 scf_transaction_t *tx = scf_transaction_create(h);
680 680 int bufsz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
681 681 char *propname = malloc(bufsz);
682 682 int r = -1;
683 683 int err;
684 684
685 685 if (h == NULL) {
686 686 /*
687 687 * Use the error stored in scf_e
688 688 */
689 689 (void) scf_set_error(scf_e);
690 690 goto cleanup;
691 691 }
692 692 if (tx == NULL)
693 693 goto cleanup;
694 694
695 695 if (propname == NULL) {
696 696 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
697 697 goto cleanup;
698 698 }
699 699
700 700 do {
701 701 nvpair_t *nvp;
702 702
703 703 /*
704 704 * make sure we have the most recent version of the pg
705 705 * start the transaction
706 706 */
707 707 if (scf_pg_update(pg) == SCF_FAILED ||
708 708 scf_transaction_start(tx, pg) != SCF_SUCCESS) {
709 709 if (check_scf_error(scf_error(), errs_2)) {
710 710 goto cleanup;
711 711 }
712 712 }
713 713
714 714 for (nvp = nvlist_next_nvpair(params, NULL); nvp != NULL;
715 715 nvp = nvlist_next_nvpair(params, nvp)) {
716 716 nvlist_t *m;
717 717 nvpair_t *p;
718 718
719 719 /* we ONLY take nvlists here */
720 720 if (nvpair_type(nvp) != DATA_TYPE_NVLIST) {
721 721 char *name = nvpair_name(nvp);
722 722
723 723 /*
724 724 * if this is output from
725 725 * smf_notify_get_params() we want to skip
726 726 * the tset value of the nvlist
727 727 */
728 728 if (strcmp(name, SCF_NOTIFY_NAME_TSET) == 0)
729 729 continue;
730 730
731 731 (void) scf_set_error(
732 732 SCF_ERROR_INVALID_ARGUMENT);
733 733 goto cleanup;
734 734 }
735 735
736 736 if (nvpair_value_nvlist(nvp, &m) != 0) {
737 737 (void) scf_set_error(
738 738 SCF_ERROR_INVALID_ARGUMENT);
739 739 goto cleanup;
740 740 }
741 741
742 742 /*
743 743 * Traverse each mechanism list
744 744 */
745 745 for (p = nvlist_next_nvpair(m, NULL); p != NULL;
746 746 p = nvlist_next_nvpair(m, p)) {
747 747 scf_transaction_entry_t *te =
748 748 scf_entry_create(h);
749 749 /* map the nvpair type to scf type */
750 750 scf_type_t type = get_scf_type(p);
751 751
752 752 if (te == NULL) {
753 753 if (scf_error() !=
754 754 SCF_ERROR_INVALID_ARGUMENT) {
755 755 scf_entry_destroy(te);
756 756 goto cleanup;
757 757 } else {
758 758 assert(0);
759 759 abort();
760 760 }
761 761 }
762 762
763 763 if (type == SCF_TYPE_INVALID) {
764 764 (void) scf_set_error(
765 765 SCF_ERROR_INVALID_ARGUMENT);
766 766 scf_entry_destroy(te);
767 767 goto cleanup;
768 768 }
769 769
770 770 if (snprintf(propname, bufsz, "%s,%s",
771 771 nvpair_name(nvp), nvpair_name(p)) >=
772 772 bufsz) {
773 773 (void) scf_set_error(
774 774 SCF_ERROR_INVALID_ARGUMENT);
775 775 scf_entry_destroy(te);
776 776 goto cleanup;
777 777 }
778 778
779 779 if (prep_transaction(tx, te, propname, type) !=
780 780 SCF_SUCCESS) {
781 781 scf_entry_destroy(te);
782 782 goto cleanup;
783 783 }
784 784
785 785 if (get_nvpair_vals(h, te, p) != SCF_SUCCESS) {
786 786 if (check_scf_error(scf_error(),
787 787 errs_2)) {
788 788 goto cleanup;
789 789 }
790 790 }
791 791 }
792 792 }
793 793 err = scf_transaction_commit(tx);
794 794 scf_transaction_destroy_children(tx);
795 795 } while (err == 0);
796 796
797 797 if (err == -1) {
798 798 if (check_scf_error(scf_error(), errs_2)) {
799 799 goto cleanup;
800 800 }
801 801 }
802 802
803 803 r = 0;
804 804
805 805 cleanup:
806 806 scf_transaction_destroy_children(tx);
807 807 scf_transaction_destroy(tx);
808 808 free(propname);
809 809
810 810 return (r);
811 811 }
812 812
813 813 /*
814 814 * Decode fmri. Populates service OR instance depending on which one is an
815 815 * exact match to the fmri parameter.
816 816 *
817 817 * The function destroys and sets the unused entity (service or instance) to
818 818 * NULL.
819 819 *
820 820 * return SCF_SUCCESS or SCF_FAILED on
821 821 * SCF_ERROR_BACKEND_ACCESS
822 822 * SCF_ERROR_CONNECTION_BROKEN
823 823 * SCF_ERROR_CONSTRAINT_VIOLATED
824 824 * SCF_ERROR_DELETED
825 825 * SCF_ERROR_HANDLE_MISMATCH
826 826 * SCF_ERROR_INTERNAL
827 827 * SCF_ERROR_INVALID_ARGUMENT
828 828 * SCF_ERROR_NO_RESOURCES
829 829 * SCF_ERROR_NOT_BOUND
830 830 * SCF_ERROR_NOT_FOUND
831 831 * SCF_ERROR_NOT_SET
832 832 */
833 833 static int
834 834 decode_fmri(const char *fmri, scf_handle_t *h, scf_service_t **s,
835 835 scf_instance_t **i)
836 836 {
837 837 if (scf_handle_decode_fmri(h, fmri, NULL, *s, NULL, NULL, NULL,
838 838 SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) {
839 839 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
840 840 scf_service_destroy(*s);
841 841 *s = NULL;
842 842 } else {
843 843 return (SCF_FAILED);
844 844 }
845 845 }
846 846 if (*s == NULL)
847 847 if (scf_handle_decode_fmri(h, fmri, NULL, NULL, *i,
848 848 NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) {
849 849 return (SCF_FAILED);
850 850 }
851 851
852 852 return (SCF_SUCCESS);
853 853 }
854 854
855 855 /*
856 856 * Return size in bytes for an SCF_TYPE_*. Not all libscf types are supported
857 857 */
858 858 static int
859 859 get_type_size(scf_type_t t)
860 860 {
861 861 switch (t) {
862 862 case SCF_TYPE_BOOLEAN:
863 863 return (sizeof (uint8_t));
864 864 case SCF_TYPE_COUNT:
865 865 return (sizeof (uint64_t));
866 866 case SCF_TYPE_INTEGER:
867 867 return (sizeof (int64_t));
868 868 case SCF_TYPE_ASTRING:
869 869 case SCF_TYPE_USTRING:
870 870 return (sizeof (void *));
871 871 default:
872 872 return (-1);
873 873 }
874 874
875 875 /*NOTREACHED*/
876 876 }
877 877
878 878 /*
879 879 * Return a pointer to the array of values according to its type
880 880 */
881 881 static void **
882 882 get_v_pointer(scf_values_t *v)
883 883 {
884 884 switch (v->value_type) {
885 885 case SCF_TYPE_BOOLEAN:
886 886 return ((void **)&v->values.v_boolean);
887 887 case SCF_TYPE_COUNT:
888 888 return ((void **)&v->values.v_count);
889 889 case SCF_TYPE_INTEGER:
890 890 return ((void **)&v->values.v_integer);
891 891 case SCF_TYPE_ASTRING:
892 892 return ((void **)&v->values.v_astring);
893 893 case SCF_TYPE_USTRING:
894 894 return ((void **)&v->values.v_ustring);
895 895 default:
896 896 return (NULL);
897 897 }
898 898
899 899 /*NOTREACHED*/
900 900 }
901 901
902 902 /*
903 903 * Populate scf_values_t value array at position c.
904 904 */
905 905 static int
906 906 get_value(scf_value_t *val, scf_values_t *v, int c, char *buf, int sz)
907 907 {
908 908 switch (v->value_type) {
909 909 case SCF_TYPE_BOOLEAN:
910 910 return (scf_value_get_boolean(val, v->values.v_boolean + c));
911 911 case SCF_TYPE_COUNT:
912 912 return (scf_value_get_count(val, v->values.v_count + c));
913 913 case SCF_TYPE_INTEGER:
914 914 return (scf_value_get_integer(val, v->values.v_integer + c));
915 915 case SCF_TYPE_ASTRING:
916 916 if (scf_value_get_astring(val, buf, sz) < 0 ||
917 917 (v->values.v_astring[c] = strdup(buf)) == NULL) {
918 918 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
919 919 return (-1);
920 920 }
921 921 return (0);
922 922 case SCF_TYPE_USTRING:
923 923 if (scf_value_get_ustring(val, buf, sz) < 0 ||
924 924 (v->values.v_ustring[c] = strdup(buf)) == NULL) {
925 925 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
926 926 return (-1);
927 927 }
928 928 return (0);
929 929 default:
930 930 return (-1);
931 931 }
932 932
933 933 /*NOTREACHED*/
934 934 }
935 935
936 936 /*
937 937 * Populate scf_values_t structure with values from prop
938 938 */
939 939 static int
940 940 values_get(scf_property_t *prop, scf_values_t *v)
941 941 {
942 942 scf_handle_t *h = scf_property_handle(prop);
943 943 scf_error_t scf_e = scf_error();
944 944 scf_value_t *val = scf_value_create(h);
945 945 scf_iter_t *it = scf_iter_create(h);
946 946 scf_type_t type = SCF_TYPE_INVALID;
947 947 ssize_t sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
948 948 char *buf = malloc(sz);
949 949 void **p;
950 950 int err, elem_sz, count, cursz;
951 951 int r = SCF_FAILED;
952 952
953 953 assert(v != NULL);
954 954 assert(v->reserved == NULL);
955 955 if (buf == NULL) {
956 956 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
957 957 goto cleanup;
958 958 }
959 959 if (h == NULL) {
960 960 /*
961 961 * Use the error stored in scf_e
962 962 */
963 963 (void) scf_set_error(scf_e);
964 964 goto cleanup;
965 965 }
966 966 if (val == NULL || it == NULL)
967 967 goto cleanup;
968 968
969 969 if (scf_property_type(prop, &type) != SCF_SUCCESS)
970 970 goto cleanup;
971 971 if (scf_property_is_type(prop, v->value_type) != SCF_SUCCESS)
972 972 goto error;
973 973
974 974 elem_sz = get_type_size(type);
975 975 assert(elem_sz > 0);
976 976
977 977 p = get_v_pointer(v);
978 978 assert(p != NULL);
979 979
980 980 cursz = count = v->value_count;
981 981 if (scf_iter_property_values(it, prop) != 0) {
982 982 goto error;
983 983 }
984 984
985 985 while ((err = scf_iter_next_value(it, val)) == 1) {
986 986 if (count + 1 >= cursz) {
987 987 void *tmp;
988 988
989 989 /* set initial size or double it */
990 990 cursz = cursz ? 2 * cursz : 8;
991 991 if ((tmp = realloc(*p, cursz * elem_sz)) == NULL) {
992 992 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
993 993 goto error;
994 994 }
995 995 *p = tmp;
996 996 }
997 997
998 998 if (get_value(val, v, count, buf, sz) != 0)
999 999 goto error;
1000 1000
1001 1001 count++;
1002 1002 }
1003 1003
1004 1004 v->value_count = count;
1005 1005
1006 1006 if (err != 0)
1007 1007 goto error;
1008 1008
1009 1009 r = SCF_SUCCESS;
1010 1010 goto cleanup;
1011 1011
1012 1012 error:
1013 1013 v->value_count = count;
1014 1014 scf_values_destroy(v);
1015 1015
1016 1016 cleanup:
1017 1017 free(buf);
1018 1018 scf_iter_destroy(it);
1019 1019 scf_value_destroy(val);
1020 1020 return (r);
1021 1021 }
1022 1022
1023 1023 /*
1024 1024 * Add values from property p to existing nvlist_t nvl. The data type in the
1025 1025 * nvlist is inferred from the scf_type_t of the property.
1026 1026 *
1027 1027 * Returns SCF_SUCCESS or SCF_FAILED on
1028 1028 * SCF_ERROR_CONNECTION_BROKEN
1029 1029 * SCF_ERROR_DELETED
1030 1030 * SCF_ERROR_HANDLE_DESTROYED
1031 1031 * SCF_ERROR_HANDLE_MISMATCH
1032 1032 * SCF_ERROR_INVALID_ARGUMENT
1033 1033 * SCF_ERROR_NO_MEMORY
1034 1034 * SCF_ERROR_NO_RESOURCES
1035 1035 * SCF_ERROR_NOT_BOUND
1036 1036 * SCF_ERROR_NOT_SET
1037 1037 * SCF_ERROR_PERMISSION_DENIED
1038 1038 * SCF_ERROR_TYPE_MISMATCH
1039 1039 */
1040 1040 static int
1041 1041 add_prop_to_nvlist(scf_property_t *p, const char *pname, nvlist_t *nvl,
1042 1042 int array)
1043 1043 {
1044 1044 scf_values_t vals = { 0 };
1045 1045 scf_type_t type, base_type;
1046 1046 int r = SCF_FAILED;
1047 1047 int err = 0;
1048 1048
1049 1049 if (p == NULL || pname == NULL || *pname == '\0' || nvl == NULL) {
1050 1050 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1051 1051 return (r);
1052 1052 }
1053 1053
1054 1054 if (scf_property_type(p, &type) != 0)
1055 1055 goto cleanup;
1056 1056
1057 1057 /*
1058 1058 * scf_values_t does not support subtypes of SCF_TYPE_USTRING,
1059 1059 * mapping them all to SCF_TYPE_USTRING
1060 1060 */
1061 1061 base_type = scf_true_base_type(type);
1062 1062 if (base_type == SCF_TYPE_ASTRING && type != SCF_TYPE_ASTRING)
1063 1063 type = SCF_TYPE_USTRING;
1064 1064
1065 1065 vals.value_type = type;
1066 1066 if (values_get(p, &vals) != SCF_SUCCESS) {
1067 1067 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) {
1068 1068 assert(0);
1069 1069 abort();
1070 1070 }
1071 1071 goto cleanup;
1072 1072 }
1073 1073
1074 1074 switch (vals.value_type) {
1075 1075 case SCF_TYPE_BOOLEAN:
1076 1076 {
1077 1077 boolean_t *v;
1078 1078 int i;
1079 1079 int n = vals.value_count;
1080 1080
1081 1081 v = calloc(n, sizeof (boolean_t));
1082 1082 if (v == NULL) {
1083 1083 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1084 1084 goto cleanup;
1085 1085 }
1086 1086 for (i = 0; i < n; ++i)
1087 1087 v[i] = (boolean_t)vals.values.v_boolean[i];
1088 1088
1089 1089 if (n == 1 && !array)
1090 1090 err = nvlist_add_boolean_value(nvl, pname, *v);
1091 1091 else
1092 1092 err = nvlist_add_boolean_array(nvl, pname,
1093 1093 v, n);
1094 1094 if (err != 0) {
1095 1095 free(v);
1096 1096 goto cleanup;
1097 1097 }
1098 1098 free(v);
1099 1099 }
1100 1100 break;
1101 1101
1102 1102 case SCF_TYPE_COUNT:
1103 1103 if (vals.value_count == 1 && !array)
1104 1104 err = nvlist_add_uint64(nvl, pname,
1105 1105 *vals.values.v_count);
1106 1106 else
1107 1107 err = nvlist_add_uint64_array(nvl, pname,
1108 1108 vals.values.v_count, vals.value_count);
1109 1109 if (err != 0)
1110 1110 goto cleanup;
1111 1111
1112 1112 break;
1113 1113
1114 1114 case SCF_TYPE_INTEGER:
1115 1115 if (vals.value_count == 1 && !array)
1116 1116 err = nvlist_add_int64(nvl, pname,
1117 1117 *vals.values.v_integer);
1118 1118 else
1119 1119 err = nvlist_add_int64_array(nvl, pname,
1120 1120 vals.values.v_integer, vals.value_count);
1121 1121 if (err != 0)
1122 1122 goto cleanup;
1123 1123
1124 1124 break;
1125 1125
1126 1126 case SCF_TYPE_ASTRING:
1127 1127 if (vals.value_count == 1 && !array)
1128 1128 err = nvlist_add_string(nvl, pname,
1129 1129 *vals.values.v_astring);
1130 1130 else
1131 1131 err = nvlist_add_string_array(nvl, pname,
1132 1132 vals.values.v_astring, vals.value_count);
1133 1133 if (err != 0)
1134 1134 goto cleanup;
1135 1135 break;
1136 1136
1137 1137 default:
1138 1138 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1139 1139 goto cleanup;
1140 1140 }
1141 1141
1142 1142 r = SCF_SUCCESS;
1143 1143 cleanup:
1144 1144 scf_values_destroy(&vals);
1145 1145 switch (err) {
1146 1146 case 0:
1147 1147 break;
1148 1148 case EINVAL:
1149 1149 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1150 1150 break;
1151 1151 case ENOMEM:
1152 1152 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1153 1153 break;
1154 1154 default:
1155 1155 /* we should *never* get here */
1156 1156 abort();
1157 1157 }
1158 1158
1159 1159 return (r);
1160 1160 }
1161 1161
1162 1162 /*
1163 1163 * Parse property name "mechanism,parameter" into separate mechanism
1164 1164 * and parameter. *mech must be freed by caller. *val points into
1165 1165 * *mech and must not be freed.
1166 1166 *
1167 1167 * Returns SCF_SUCCESS or SCF_FAILED on
1168 1168 * SCF_ERROR_NO_MEMORY
1169 1169 * SCF_ERROR_NOT_FOUND
1170 1170 */
1171 1171 static int
1172 1172 get_mech_name(const char *name, char **mech, char **val)
1173 1173 {
1174 1174 char *p;
1175 1175 char *m;
1176 1176
1177 1177 if ((m = strdup(name)) == NULL) {
1178 1178 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1179 1179 return (SCF_FAILED);
1180 1180 }
1181 1181 if ((p = strchr(m, ',')) == NULL) {
1182 1182 free(m);
1183 1183 (void) scf_set_error(SCF_ERROR_NOT_FOUND);
1184 1184 return (SCF_FAILED);
1185 1185 }
1186 1186 *p = '\0';
1187 1187 *val = p + 1;
1188 1188 *mech = m;
1189 1189
1190 1190 return (SCF_SUCCESS);
1191 1191 }
1192 1192
1193 1193 /*
1194 1194 * Return the number of transitions in a transition set.
1195 1195 * If the transition set is invalid, it returns zero.
1196 1196 */
1197 1197 static uint_t
1198 1198 num_of_transitions(int32_t t)
1199 1199 {
1200 1200 int i;
1201 1201 int n = 0;
1202 1202
1203 1203 if (SCF_TRANS_VALID(t)) {
1204 1204 for (i = 0x1; i < SCF_STATE_ALL; i <<= 1) {
1205 1205 if (i & t)
1206 1206 ++n;
1207 1207 if (SCF_TRANS_INITIAL_STATE(t) & i)
1208 1208 ++n;
1209 1209 }
1210 1210 }
1211 1211
1212 1212 return (n);
1213 1213 }
1214 1214
1215 1215 /*
1216 1216 * Return the SCF_STATE_* macro value for the state in the FMA classes for
1217 1217 * SMF state transitions. They are of type:
1218 1218 * SCF_SVC_TRANSITION_CLASS.<state>
1219 1219 * ireport.os.smf.state-transition.<state>
1220 1220 */
1221 1221 static int32_t
1222 1222 class_to_transition(const char *c)
1223 1223 {
1224 1224 const char *p;
1225 1225 int r = 0;
1226 1226 size_t n;
1227 1227
1228 1228 if (!is_svc_stn(c)) {
1229 1229 return (0);
1230 1230 }
1231 1231
1232 1232 /*
1233 1233 * if we get here, c is SCF_SVC_TRANSITION_CLASS or longer
1234 1234 */
1235 1235 p = c + strlen(SCF_SVC_TRANSITION_CLASS);
1236 1236 if (*p == '.')
1237 1237 ++p;
1238 1238 else
1239 1239 return (0);
1240 1240
1241 1241 if ((n = base_class_len(p)) == 0)
1242 1242 return (0);
1243 1243
1244 1244 if ((r = state_from_string(p, n)) == -1)
1245 1245 r = 0;
1246 1246
1247 1247 return (r);
1248 1248 }
1249 1249
1250 1250 /*
1251 1251 * return SCF_SUCCESS or SCF_FAILED on
1252 1252 * SCF_ERROR_BACKEND_ACCESS
1253 1253 * SCF_ERROR_BACKEND_READONLY
1254 1254 * SCF_ERROR_CONNECTION_BROKEN
1255 1255 * SCF_ERROR_DELETED
1256 1256 * SCF_ERROR_INTERNAL
1257 1257 * SCF_ERROR_INVALID_ARGUMENT
1258 1258 * SCF_ERROR_NO_MEMORY
1259 1259 * SCF_ERROR_NO_RESOURCES
1260 1260 * SCF_ERROR_NOT_FOUND
1261 1261 * SCF_ERROR_PERMISSION_DENIED
1262 1262 */
1263 1263 int
1264 1264 smf_notify_set_params(const char *class, nvlist_t *attr)
1265 1265 {
1266 1266 uint32_t ver;
1267 1267 int32_t tset;
1268 1268 scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION);
1269 1269 scf_error_t scf_e = scf_error();
1270 1270 scf_service_t *s = scf_service_create(h);
1271 1271 scf_instance_t *i = scf_instance_create(h);
1272 1272 scf_propertygroup_t *pg = scf_pg_create(h);
1273 1273 nvlist_t *params = NULL;
1274 1274 char *fmri = (char *)SCF_NOTIFY_PARAMS_INST;
1275 1275 char *pgname = NULL;
1276 1276 int r = SCF_FAILED;
1277 1277 boolean_t is_stn;
1278 1278 int j;
1279 1279
1280 1280 assert(class != NULL);
1281 1281 if (h == NULL) {
1282 1282 /*
1283 1283 * use saved error if _scf_handle_create_and_bind() fails
1284 1284 */
1285 1285 (void) scf_set_error(scf_e);
1286 1286 goto cleanup;
1287 1287 }
1288 1288 if (i == NULL || s == NULL || pg == NULL)
1289 1289 goto cleanup;
1290 1290
1291 1291 /* check version */
1292 1292 if (nvlist_lookup_uint32(attr, SCF_NOTIFY_NAME_VERSION, &ver) != 0 ||
1293 1293 ver != SCF_NOTIFY_PARAMS_VERSION) {
1294 1294 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1295 1295 goto cleanup;
1296 1296 }
1297 1297
1298 1298 if (nvlist_lookup_nvlist(attr, SCF_NOTIFY_PARAMS, ¶ms) != 0) {
1299 1299 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1300 1300 goto cleanup;
1301 1301 }
1302 1302
1303 1303 is_stn = is_svc_stn(class);
1304 1304 /* special case SMF state transition notification */
1305 1305 if (is_stn &&
1306 1306 (nvlist_lookup_string(attr, SCF_NOTIFY_NAME_FMRI, &fmri) != 0 ||
1307 1307 nvlist_lookup_int32(attr, SCF_NOTIFY_NAME_TSET, &tset) != 0 ||
1308 1308 !SCF_TRANS_VALID(tset))) {
1309 1309 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1310 1310 goto cleanup;
1311 1311 }
1312 1312 if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS)
1313 1313 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
1314 1314 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1315 1315 } else if (check_scf_error(scf_error(), errs_1)) {
1316 1316 goto cleanup;
1317 1317 }
1318 1318
1319 1319 if (is_stn) {
1320 1320 tset |= class_to_transition(class);
1321 1321
1322 1322 if (!SCF_TRANS_VALID(tset)) {
1323 1323 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1324 1324 goto cleanup;
1325 1325 }
1326 1326
1327 1327 for (j = 0; st_pgnames[j].st_pgname != NULL; ++j) {
1328 1328 /* if this transition is not in the tset, continue */
1329 1329 if (!(tset & st_pgnames[j].st_state))
1330 1330 continue;
1331 1331
1332 1332 if (get_or_add_pg(s, i, st_pgnames[j].st_pgname,
1333 1333 SCF_NOTIFY_PARAMS_PG_TYPE, 0, pg) != 0 &&
1334 1334 check_scf_error(scf_error(), errs_2))
1335 1335 goto cleanup;
1336 1336
1337 1337 if (notify_set_params(pg, params) != 0)
1338 1338 goto cleanup;
1339 1339 }
1340 1340 if (s == NULL) {
1341 1341 /* We only need to refresh the instance */
1342 1342 if (_smf_refresh_instance_i(i) != 0 &&
1343 1343 check_scf_error(scf_error(), errs_1))
1344 1344 goto cleanup;
1345 1345 } else {
1346 1346 /* We have to refresh all instances in the service */
1347 1347 if (_smf_refresh_all_instances(s) != 0 &&
1348 1348 check_scf_error(scf_error(), errs_1))
1349 1349 goto cleanup;
1350 1350 }
1351 1351 } else {
1352 1352 if ((pgname = class_to_pgname(class)) == NULL)
1353 1353 goto cleanup;
1354 1354 if (get_or_add_pg(s, i, pgname, SCF_GROUP_APPLICATION, 0, pg) !=
1355 1355 0) {
1356 1356 if (check_scf_error(scf_error(), errs_2)) {
1357 1357 goto cleanup;
1358 1358 }
1359 1359 }
1360 1360 if (notify_set_params(pg, params) != 0) {
1361 1361 goto cleanup;
1362 1362 }
1363 1363 if (_smf_refresh_instance_i(i) != 0 &&
1364 1364 check_scf_error(scf_error(), errs_1))
1365 1365 goto cleanup;
1366 1366 }
1367 1367
1368 1368 r = SCF_SUCCESS;
1369 1369 cleanup:
1370 1370 scf_instance_destroy(i);
1371 1371 scf_service_destroy(s);
1372 1372 scf_pg_destroy(pg);
1373 1373 scf_handle_destroy(h);
1374 1374 free(pgname);
1375 1375
1376 1376 return (r);
1377 1377 }
1378 1378
1379 1379 /*
1380 1380 * returns SCF_SUCCESS or SCF_FAILED on
1381 1381 * SCF_ERROR_CONNECTION_BROKEN
1382 1382 * SCF_ERROR_DELETED
1383 1383 * SCF_ERROR_HANDLE_DESTROYED
1384 1384 * SCF_ERROR_HANDLE_MISMATCH
1385 1385 * SCF_ERROR_INVALID_ARGUMENT
1386 1386 * SCF_ERROR_NO_MEMORY
1387 1387 * SCF_ERROR_NO_RESOURCES
1388 1388 * SCF_ERROR_NOT_BOUND
1389 1389 * SCF_ERROR_NOT_FOUND
1390 1390 * SCF_ERROR_NOT_SET
1391 1391 * SCF_ERROR_PERMISSION_DENIED
1392 1392 */
1393 1393 int
1394 1394 _scf_notify_get_params(scf_propertygroup_t *pg, nvlist_t *params)
1395 1395 {
1396 1396 scf_handle_t *h = scf_pg_handle(pg);
1397 1397 scf_error_t scf_e = scf_error();
1398 1398 scf_property_t *p = scf_property_create(h);
1399 1399 scf_iter_t *it = scf_iter_create(h);
1400 1400 int sz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
1401 1401 char *name = malloc(sz);
1402 1402 int r = SCF_FAILED;
1403 1403 int err;
1404 1404
1405 1405 if (h == NULL) {
1406 1406 /*
1407 1407 * Use the error stored in scf_e
1408 1408 */
1409 1409 (void) scf_set_error(scf_e);
1410 1410 goto cleanup;
1411 1411 }
1412 1412 if (it == NULL || p == NULL)
1413 1413 goto cleanup;
1414 1414
1415 1415 if (name == NULL) {
1416 1416 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1417 1417 goto cleanup;
1418 1418 }
1419 1419
1420 1420 if (scf_iter_pg_properties(it, pg) != SCF_SUCCESS) {
1421 1421 if (check_scf_error(scf_error(), errs_1)) {
1422 1422 goto cleanup;
1423 1423 }
1424 1424 }
1425 1425
1426 1426 while ((err = scf_iter_next_property(it, p)) == 1) {
1427 1427 nvlist_t *nvl;
1428 1428 int nvl_new = 0;
1429 1429 char *mech;
1430 1430 char *val;
1431 1431
1432 1432 if (scf_property_get_name(p, name, sz) == SCF_FAILED) {
1433 1433 if (check_scf_error(scf_error(), errs_1)) {
1434 1434 goto cleanup;
1435 1435 }
1436 1436 }
1437 1437
1438 1438 if (get_mech_name(name, &mech, &val) != SCF_SUCCESS) {
1439 1439 if (scf_error() == SCF_ERROR_NOT_FOUND)
1440 1440 continue;
1441 1441 goto cleanup;
1442 1442 }
1443 1443
1444 1444 if (nvlist_lookup_nvlist(params, mech, &nvl) != 0) {
1445 1445 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
1446 1446 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1447 1447 free(mech);
1448 1448 goto cleanup;
1449 1449 }
1450 1450 nvl_new = 1;
1451 1451 }
1452 1452
1453 1453 if (add_prop_to_nvlist(p, val, nvl, 1) != SCF_SUCCESS) {
1454 1454 if (check_scf_error(scf_error(), errs_2)) {
1455 1455 free(mech);
1456 1456 nvlist_free(nvl);
1457 1457 goto cleanup;
1458 1458 }
1459 1459 }
1460 1460 if (nvl_new) {
1461 1461 if (nvlist_add_nvlist(params, mech, nvl) != 0) {
1462 1462 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1463 1463 free(mech);
1464 1464 nvlist_free(nvl);
1465 1465 goto cleanup;
1466 1466 }
1467 1467 nvlist_free(nvl);
1468 1468 }
1469 1469
1470 1470 free(mech);
1471 1471 }
1472 1472
1473 1473 if (err == 0) {
1474 1474 r = SCF_SUCCESS;
1475 1475 } else if (check_scf_error(scf_error(), errs_2)) {
1476 1476 goto cleanup;
1477 1477 }
1478 1478
1479 1479 cleanup:
1480 1480 scf_iter_destroy(it);
1481 1481 scf_property_destroy(p);
1482 1482 free(name);
1483 1483
1484 1484 return (r);
1485 1485 }
1486 1486
1487 1487 /*
1488 1488 * Look up pg containing an SMF state transition parameters. If it cannot find
1489 1489 * the pg in the composed view of the instance, it will look in the global
1490 1490 * instance for the system wide parameters.
1491 1491 * Instance, service and global instance have to be passed by caller.
1492 1492 *
1493 1493 * returns SCF_SUCCESS or SCF_FAILED on
1494 1494 * SCF_ERROR_BACKEND_ACCESS
1495 1495 * SCF_ERROR_CONNECTION_BROKEN
1496 1496 * SCF_ERROR_DELETED
1497 1497 * SCF_ERROR_HANDLE_DESTROYED
1498 1498 * SCF_ERROR_HANDLE_MISMATCH
1499 1499 * SCF_ERROR_INTERNAL
1500 1500 * SCF_ERROR_INVALID_ARGUMENT
1501 1501 * SCF_ERROR_NO_MEMORY
1502 1502 * SCF_ERROR_NO_RESOURCES
1503 1503 * SCF_ERROR_NOT_BOUND
1504 1504 * SCF_ERROR_NOT_FOUND
1505 1505 * SCF_ERROR_NOT_SET
1506 1506 */
1507 1507 static int
1508 1508 get_stn_pg(scf_service_t *s, scf_instance_t *i, scf_instance_t *g,
1509 1509 const char *pgname, scf_propertygroup_t *pg)
1510 1510 {
1511 1511 if (get_pg(s, i, pgname, pg, 1) == 0 ||
1512 1512 scf_error() == SCF_ERROR_NOT_FOUND &&
1513 1513 get_pg(NULL, g, pgname, pg, 0) == 0)
1514 1514 return (SCF_SUCCESS);
1515 1515
1516 1516 return (SCF_FAILED);
1517 1517 }
1518 1518
1519 1519 /*
1520 1520 * Populates nvlist_t params with the source fmri for the pg
1521 1521 *
1522 1522 * return SCF_SUCCESS or SCF_FAILED on
1523 1523 * SCF_ERROR_DELETED
1524 1524 * SCF_ERROR_CONNECTION_BROKEN
1525 1525 * SCF_ERROR_NO_MEMORY
1526 1526 */
1527 1527 static int
1528 1528 get_pg_source(scf_propertygroup_t *pg, nvlist_t *params)
1529 1529 {
1530 1530 size_t sz = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH) + 1;
1531 1531 char *fmri = malloc(sz);
1532 1532 char *p;
1533 1533 int r = SCF_FAILED;
1534 1534
1535 1535 if (fmri == NULL) {
1536 1536 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1537 1537 goto out;
1538 1538 }
1539 1539
1540 1540 if (scf_pg_to_fmri(pg, fmri, sz) == -1) {
1541 1541 if (check_scf_error(scf_error(), errs_1)) {
1542 1542 goto out;
1543 1543 }
1544 1544 }
1545 1545
1546 1546 /* get rid of the properties part of the pg source */
1547 1547 if ((p = strrchr(fmri, ':')) != NULL && p > fmri)
1548 1548 *(p - 1) = '\0';
1549 1549 if (nvlist_add_string(params, SCF_NOTIFY_PARAMS_SOURCE_NAME, fmri) !=
1550 1550 0) {
1551 1551 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1552 1552 goto out;
1553 1553 }
1554 1554
1555 1555 r = SCF_SUCCESS;
1556 1556 out:
1557 1557 free(fmri);
1558 1558 return (r);
1559 1559 }
1560 1560
1561 1561 /*
1562 1562 * Specialized function to get SMF state transition notification parameters
1563 1563 *
1564 1564 * return SCF_SUCCESS or SCF_FAILED on
1565 1565 * SCF_ERROR_BACKEND_ACCESS
1566 1566 * SCF_ERROR_CONNECTION_BROKEN
1567 1567 * SCF_ERROR_DELETED
1568 1568 * SCF_ERROR_INTERNAL
1569 1569 * SCF_ERROR_INVALID_ARGUMENT
1570 1570 * SCF_ERROR_NO_MEMORY
1571 1571 * SCF_ERROR_NO_RESOURCES
1572 1572 * SCF_ERROR_NOT_FOUND
1573 1573 * SCF_ERROR_PERMISSION_DENIED
1574 1574 */
1575 1575 int
1576 1576 _scf_get_svc_notify_params(const char *fmri, nvlist_t *nvl, int32_t tset,
1577 1577 int getsource, int getglobal)
1578 1578 {
1579 1579 scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION);
1580 1580 scf_error_t scf_e = scf_error();
1581 1581 scf_service_t *s = scf_service_create(h);
1582 1582 scf_instance_t *i = scf_instance_create(h);
1583 1583 scf_instance_t *g = scf_instance_create(h);
1584 1584 scf_propertygroup_t *pg = scf_pg_create(h);
1585 1585 int r = SCF_FAILED;
1586 1586 nvlist_t **params = NULL;
1587 1587 uint_t c, nvl_num = 0;
1588 1588 int not_found = 1;
1589 1589 int j;
1590 1590 const char *pgname;
1591 1591
1592 1592 assert(fmri != NULL && nvl != NULL);
1593 1593 if (h == NULL) {
1594 1594 /*
1595 1595 * use saved error if _scf_handle_create_and_bind() fails
1596 1596 */
1597 1597 (void) scf_set_error(scf_e);
1598 1598 goto cleanup;
1599 1599 }
1600 1600 if (s == NULL || i == NULL || g == NULL || pg == NULL)
1601 1601 goto cleanup;
1602 1602
1603 1603 if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS ||
1604 1604 scf_handle_decode_fmri(h, SCF_INSTANCE_GLOBAL, NULL, NULL, g, NULL,
1605 1605 NULL, SCF_DECODE_FMRI_EXACT) != 0) {
1606 1606 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED) {
1607 1607 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1608 1608 } else if (check_scf_error(scf_error(), errs_1)) {
1609 1609 goto cleanup;
1610 1610 }
1611 1611 }
1612 1612
1613 1613 nvl_num = num_of_transitions(tset);
1614 1614 if ((params = calloc(nvl_num, sizeof (nvlist_t *))) == NULL) {
1615 1615 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1616 1616 goto cleanup;
1617 1617 }
1618 1618
1619 1619 for (c = 0; c < nvl_num; ++c)
1620 1620 if (nvlist_alloc(params + c, NV_UNIQUE_NAME, 0) != 0) {
1621 1621 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1622 1622 goto cleanup;
1623 1623 }
1624 1624
1625 1625 for (c = 0, j = 0; st_pgnames[j].st_pgname != NULL; ++j) {
1626 1626 /* if this transition is not in the tset, continue */
1627 1627 if (!(tset & st_pgnames[j].st_state))
1628 1628 continue;
1629 1629
1630 1630 assert(c < nvl_num);
1631 1631 pgname = st_pgnames[j].st_pgname;
1632 1632
1633 1633 if (nvlist_add_int32(params[c], SCF_NOTIFY_NAME_TSET,
1634 1634 st_pgnames[j].st_state) != 0) {
1635 1635 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1636 1636 goto cleanup;
1637 1637 }
1638 1638 if ((getglobal ? get_stn_pg(s, i, g, pgname, pg) :
1639 1639 get_pg(s, i, pgname, pg, 1)) == SCF_SUCCESS) {
1640 1640 not_found = 0;
1641 1641 if (_scf_notify_get_params(pg, params[c]) !=
1642 1642 SCF_SUCCESS)
1643 1643 goto cleanup;
1644 1644 if (getsource && get_pg_source(pg, params[c]) !=
1645 1645 SCF_SUCCESS)
1646 1646 goto cleanup;
1647 1647 } else if (scf_error() == SCF_ERROR_NOT_FOUND ||
1648 1648 scf_error() == SCF_ERROR_DELETED) {
1649 1649 /* keep driving */
1650 1650 /*EMPTY*/
1651 1651 } else if (check_scf_error(scf_error(), errs_1)) {
1652 1652 goto cleanup;
1653 1653 }
1654 1654 ++c;
1655 1655 }
1656 1656
1657 1657 if (not_found) {
1658 1658 (void) scf_set_error(SCF_ERROR_NOT_FOUND);
1659 1659 goto cleanup;
1660 1660 }
1661 1661
1662 1662 assert(c == nvl_num);
1663 1663
1664 1664 if (nvlist_add_nvlist_array(nvl, SCF_NOTIFY_PARAMS, params, nvl_num) !=
1665 1665 0 || nvlist_add_uint32(nvl, SCF_NOTIFY_NAME_VERSION,
1666 1666 SCF_NOTIFY_PARAMS_VERSION) != 0) {
1667 1667 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1668 1668 goto cleanup;
1669 1669 }
1670 1670
1671 1671 r = SCF_SUCCESS;
1672 1672
1673 1673 cleanup:
1674 1674 scf_pg_destroy(pg);
1675 1675 scf_instance_destroy(i);
1676 1676 scf_instance_destroy(g);
1677 1677 scf_service_destroy(s);
1678 1678 scf_handle_destroy(h);
1679 1679 if (params != NULL)
1680 1680 for (c = 0; c < nvl_num; ++c)
1681 1681 nvlist_free(params[c]);
1682 1682 free(params);
1683 1683
1684 1684 return (r);
1685 1685 }
1686 1686
1687 1687 /*
1688 1688 * Specialized function to get fma notification parameters
1689 1689 *
1690 1690 * return SCF_SUCCESS or SCF_FAILED on
1691 1691 * SCF_ERROR_BACKEND_ACCESS
1692 1692 * SCF_ERROR_CONNECTION_BROKEN
1693 1693 * SCF_ERROR_DELETED
1694 1694 * SCF_ERROR_INTERNAL
1695 1695 * SCF_ERROR_INVALID_ARGUMENT
1696 1696 * SCF_ERROR_NO_MEMORY
1697 1697 * SCF_ERROR_NO_RESOURCES
1698 1698 * SCF_ERROR_NOT_FOUND
1699 1699 * SCF_ERROR_PERMISSION_DENIED
1700 1700 */
1701 1701 int
1702 1702 _scf_get_fma_notify_params(const char *class, nvlist_t *nvl, int getsource)
1703 1703 {
1704 1704 scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION);
1705 1705 scf_error_t scf_e = scf_error();
1706 1706 scf_instance_t *i = scf_instance_create(h);
1707 1707 scf_propertygroup_t *pg = scf_pg_create(h);
1708 1708 int r = SCF_FAILED;
1709 1709 nvlist_t *params = NULL;
1710 1710 char *pgname = NULL;
1711 1711
1712 1712 if (h == NULL) {
1713 1713 /*
1714 1714 * use saved error if _scf_handle_create_and_bind() fails
1715 1715 */
1716 1716 (void) scf_set_error(scf_e);
1717 1717 goto cleanup;
1718 1718 }
1719 1719 if (i == NULL || pg == NULL)
1720 1720 goto cleanup;
1721 1721
1722 1722 if (scf_handle_decode_fmri(h, SCF_NOTIFY_PARAMS_INST, NULL, NULL, i,
1723 1723 NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS) {
1724 1724 if (check_scf_error(scf_error(), errs_1)) {
1725 1725 goto cleanup;
1726 1726 }
1727 1727 }
1728 1728
1729 1729 if ((pgname = class_to_pgname(class)) == NULL)
1730 1730 goto cleanup;
1731 1731
1732 1732 while (get_pg(NULL, i, pgname, pg, 0) != 0) {
1733 1733 if (scf_error() == SCF_ERROR_NOT_FOUND) {
1734 1734 char *p = strrchr(pgname, '.');
1735 1735
1736 1736 if (p != NULL) {
1737 1737 *p = ',';
1738 1738 /*
1739 1739 * since the resulting string is shorter,
1740 1740 * there is no risk of buffer overflow
1741 1741 */
1742 1742 (void) strcpy(p + 1, SCF_NOTIFY_PG_POSTFIX);
1743 1743 continue;
1744 1744 }
1745 1745 }
1746 1746
1747 1747 if (check_scf_error(scf_error(), errs_1)) {
1748 1748 goto cleanup;
1749 1749 }
1750 1750 }
1751 1751
1752 1752 if (nvlist_alloc(¶ms, NV_UNIQUE_NAME, 0) != 0) {
1753 1753 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1754 1754 goto cleanup;
1755 1755 }
1756 1756
1757 1757 if (_scf_notify_get_params(pg, params) != SCF_SUCCESS)
1758 1758 goto cleanup;
1759 1759
1760 1760 if (getsource && get_pg_source(pg, params) != SCF_SUCCESS)
1761 1761 goto cleanup;
1762 1762
↓ open down ↓ |
1762 lines elided |
↑ open up ↑ |
1763 1763 if (nvlist_add_nvlist_array(nvl, SCF_NOTIFY_PARAMS, ¶ms, 1) != 0 ||
1764 1764 nvlist_add_uint32(nvl, SCF_NOTIFY_NAME_VERSION,
1765 1765 SCF_NOTIFY_PARAMS_VERSION) != 0) {
1766 1766 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1767 1767 goto cleanup;
1768 1768 }
1769 1769
1770 1770 r = SCF_SUCCESS;
1771 1771
1772 1772 cleanup:
1773 - if (params)
1774 - nvlist_free(params);
1773 + nvlist_free(params);
1775 1774 scf_pg_destroy(pg);
1776 1775 scf_instance_destroy(i);
1777 1776 scf_handle_destroy(h);
1778 1777 free(pgname);
1779 1778
1780 1779 return (r);
1781 1780 }
1782 1781
1783 1782 /*
1784 1783 * Retrieve the notification parameters for the Event described in the
1785 1784 * input nvlist_t nvl.
1786 1785 * The function will allocate an nvlist_t to store the notification
1787 1786 * parameters. The notification parameters in the output nvlist will have
1788 1787 * the following format:
1789 1788 *
1790 1789 * version (uint32_t)
1791 1790 * SCF_NOTIFY_PARAMS (array of embedded nvlists)
1792 1791 * (start of notify-params[0])
1793 1792 * tset (int32_t)
1794 1793 * <mechanism-name> (embedded nvlist)
1795 1794 * <parameter-name> <parameter-type>
1796 1795 * ...
1797 1796 * (end <mechanism-name>)
1798 1797 * ...
1799 1798 * (end of notify-params[0])
1800 1799 * ...
1801 1800 *
1802 1801 * return SCF_SUCCESS or SCF_FAILED on
1803 1802 * SCF_ERROR_BACKEND_ACCESS
1804 1803 * SCF_ERROR_CONNECTION_BROKEN
1805 1804 * SCF_ERROR_DELETED
1806 1805 * SCF_ERROR_INTERNAL
1807 1806 * SCF_ERROR_INVALID_ARGUMENT
1808 1807 * SCF_ERROR_NO_MEMORY
1809 1808 * SCF_ERROR_NO_RESOURCES
1810 1809 * SCF_ERROR_NOT_FOUND
1811 1810 * SCF_ERROR_PERMISSION_DENIED
1812 1811 */
1813 1812 int
1814 1813 smf_notify_get_params(nvlist_t **params, nvlist_t *nvl)
1815 1814 {
1816 1815 char *class;
1817 1816 char *from; /* from state */
1818 1817 char *to; /* to state */
1819 1818 nvlist_t *attr;
1820 1819 char *fmri;
1821 1820 int32_t tset = 0;
1822 1821 int r = SCF_FAILED;
1823 1822
1824 1823 if (params == NULL || nvlist_lookup_string(nvl, "class", &class) != 0) {
1825 1824 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1826 1825 return (r);
1827 1826 }
1828 1827 if (nvlist_alloc(params, NV_UNIQUE_NAME, 0) != 0) {
1829 1828 (void) scf_set_error(SCF_ERROR_NO_MEMORY);
1830 1829 return (r);
1831 1830 }
1832 1831
1833 1832 if (is_svc_stn(class)) {
1834 1833 if (nvlist_lookup_nvlist(nvl, "attr", &attr) != 0 ||
1835 1834 nvlist_lookup_string(attr, "svc-string", &fmri) != 0 ||
1836 1835 nvlist_lookup_string(attr, "from-state", &from) != 0 ||
1837 1836 nvlist_lookup_string(attr, "to-state", &to) != 0) {
1838 1837 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1839 1838 goto cleanup;
1840 1839 }
1841 1840
1842 1841 tset = SCF_TRANS(smf_state_from_string(from),
1843 1842 smf_state_from_string(to));
1844 1843 if (!SCF_TRANS_VALID(tset)) {
1845 1844 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1846 1845 goto cleanup;
1847 1846 }
1848 1847 tset |= class_to_transition(class);
1849 1848
1850 1849 r = _scf_get_svc_notify_params(fmri, *params, tset, 0, 1);
1851 1850 } else {
1852 1851 r = _scf_get_fma_notify_params(class, *params, 0);
1853 1852 }
1854 1853
1855 1854 cleanup:
1856 1855 if (r == SCF_FAILED) {
1857 1856 nvlist_free(*params);
1858 1857 *params = NULL;
1859 1858 }
1860 1859
1861 1860 return (r);
1862 1861 }
1863 1862
1864 1863 /*
1865 1864 * return SCF_SUCCESS or SCF_FAILED on
1866 1865 * SCF_ERROR_BACKEND_ACCESS
1867 1866 * SCF_ERROR_BACKEND_READONLY
1868 1867 * SCF_ERROR_CONNECTION_BROKEN
1869 1868 * SCF_ERROR_DELETED
1870 1869 * SCF_ERROR_INTERNAL
1871 1870 * SCF_ERROR_INVALID_ARGUMENT
1872 1871 * SCF_ERROR_NO_MEMORY
1873 1872 * SCF_ERROR_NO_RESOURCES
1874 1873 * SCF_ERROR_NOT_FOUND
1875 1874 * SCF_ERROR_PERMISSION_DENIED
1876 1875 */
1877 1876 int
1878 1877 smf_notify_del_params(const char *class, const char *fmri, int32_t tset)
1879 1878 {
1880 1879 scf_handle_t *h = _scf_handle_create_and_bind(SCF_VERSION);
1881 1880 scf_error_t scf_e = scf_error();
1882 1881 scf_service_t *s = scf_service_create(h);
1883 1882 scf_instance_t *i = scf_instance_create(h);
1884 1883 scf_propertygroup_t *pg = scf_pg_create(h);
1885 1884 int r = SCF_FAILED;
1886 1885 char *pgname = NULL;
1887 1886 int j;
1888 1887
1889 1888 if (class == NULL) {
1890 1889 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1891 1890 goto cleanup;
1892 1891 }
1893 1892
1894 1893 if (h == NULL) {
1895 1894 /*
1896 1895 * use saved error if _scf_handle_create_and_bind() fails
1897 1896 */
1898 1897 (void) scf_set_error(scf_e);
1899 1898 goto cleanup;
1900 1899 }
1901 1900 if (s == NULL || i == NULL || pg == NULL)
1902 1901 goto cleanup;
1903 1902
1904 1903 if (is_svc_stn(class)) {
1905 1904 tset |= class_to_transition(class);
1906 1905
1907 1906 if (!SCF_TRANS_VALID(tset) || fmri == NULL) {
1908 1907 (void) scf_set_error(SCF_ERROR_INVALID_ARGUMENT);
1909 1908 goto cleanup;
1910 1909 }
1911 1910
1912 1911 if (decode_fmri(fmri, h, &s, &i) != SCF_SUCCESS) {
1913 1912 if (scf_error() == SCF_ERROR_CONSTRAINT_VIOLATED)
1914 1913 (void) scf_set_error(
1915 1914 SCF_ERROR_INVALID_ARGUMENT);
1916 1915 if (check_scf_error(scf_error(), errs_1)) {
1917 1916 goto cleanup;
1918 1917 }
1919 1918 }
1920 1919
1921 1920 for (j = 0; st_pgnames[j].st_pgname != NULL; ++j) {
1922 1921 /* if this transition is not in the tset, continue */
1923 1922 if (!(tset & st_pgnames[j].st_state))
1924 1923 continue;
1925 1924
1926 1925 if (del_pg(s, i, st_pgnames[j].st_pgname, pg) !=
1927 1926 SCF_SUCCESS &&
1928 1927 scf_error() != SCF_ERROR_DELETED &&
1929 1928 scf_error() != SCF_ERROR_NOT_FOUND) {
1930 1929 if (check_scf_error(scf_error(),
1931 1930 errs_1)) {
1932 1931 goto cleanup;
1933 1932 }
1934 1933 }
1935 1934 }
1936 1935 if (s == NULL) {
1937 1936 /* We only need to refresh the instance */
1938 1937 if (_smf_refresh_instance_i(i) != 0 &&
1939 1938 check_scf_error(scf_error(), errs_1))
1940 1939 goto cleanup;
1941 1940 } else {
1942 1941 /* We have to refresh all instances in the service */
1943 1942 if (_smf_refresh_all_instances(s) != 0 &&
1944 1943 check_scf_error(scf_error(), errs_1))
1945 1944 goto cleanup;
1946 1945 }
1947 1946 } else {
1948 1947 if ((pgname = class_to_pgname(class)) == NULL)
1949 1948 goto cleanup;
1950 1949
1951 1950 if (scf_handle_decode_fmri(h, SCF_NOTIFY_PARAMS_INST, NULL,
1952 1951 NULL, i, NULL, NULL, SCF_DECODE_FMRI_EXACT) != SCF_SUCCESS)
1953 1952 goto cleanup;
1954 1953
1955 1954 if (del_pg(NULL, i, pgname, pg) != SCF_SUCCESS &&
1956 1955 scf_error() != SCF_ERROR_DELETED &&
1957 1956 scf_error() != SCF_ERROR_NOT_FOUND) {
1958 1957 if (check_scf_error(scf_error(), errs_1)) {
1959 1958 goto cleanup;
1960 1959 }
1961 1960 }
1962 1961
1963 1962 if (_smf_refresh_instance_i(i) != 0 &&
1964 1963 check_scf_error(scf_error(), errs_1))
1965 1964 goto cleanup;
1966 1965 }
1967 1966
1968 1967
1969 1968 r = SCF_SUCCESS;
1970 1969
1971 1970 cleanup:
1972 1971 scf_pg_destroy(pg);
1973 1972 scf_instance_destroy(i);
1974 1973 scf_service_destroy(s);
1975 1974 scf_handle_destroy(h);
1976 1975 free(pgname);
1977 1976
1978 1977 return (r);
1979 1978 }
↓ open down ↓ |
195 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX