17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53ad28c1eSrm * Common Development and Distribution License (the "License").
63ad28c1eSrm * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217257d1b4Sraf
227c478bd9Sstevel@tonic-gate /*
23f6e214c7SGavin Maltby * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24ac0324d2SJerry Jelinek * Copyright (c) 2013, Joyent, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
27f6e214c7SGavin Maltby #include <libintl.h>
287c478bd9Sstevel@tonic-gate #include <librestart.h>
297c478bd9Sstevel@tonic-gate #include <librestart_priv.h>
307c478bd9Sstevel@tonic-gate #include <libscf.h>
317c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include <assert.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <dlfcn.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <exec_attr.h>
387c478bd9Sstevel@tonic-gate #include <grp.h>
397c478bd9Sstevel@tonic-gate #include <libsysevent.h>
407c478bd9Sstevel@tonic-gate #include <libuutil.h>
417c478bd9Sstevel@tonic-gate #include <limits.h>
427c478bd9Sstevel@tonic-gate #include <link.h>
437c478bd9Sstevel@tonic-gate #include <malloc.h>
447c478bd9Sstevel@tonic-gate #include <pool.h>
457c478bd9Sstevel@tonic-gate #include <priv.h>
467c478bd9Sstevel@tonic-gate #include <project.h>
477c478bd9Sstevel@tonic-gate #include <pthread.h>
487c478bd9Sstevel@tonic-gate #include <pwd.h>
497c478bd9Sstevel@tonic-gate #include <secdb.h>
507c478bd9Sstevel@tonic-gate #include <signal.h>
517c478bd9Sstevel@tonic-gate #include <stdlib.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <syslog.h>
547c478bd9Sstevel@tonic-gate #include <sys/corectl.h>
557c478bd9Sstevel@tonic-gate #include <sys/machelf.h>
56d2a70789SRichard Lowe #include <sys/secflags.h>
577c478bd9Sstevel@tonic-gate #include <sys/task.h>
587c478bd9Sstevel@tonic-gate #include <sys/types.h>
597c478bd9Sstevel@tonic-gate #include <time.h>
607c478bd9Sstevel@tonic-gate #include <unistd.h>
617c478bd9Sstevel@tonic-gate #include <ucontext.h>
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a))
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true"
667c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill"
677c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process"
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.")
707c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.")
717c478bd9Sstevel@tonic-gate
722c65c8b0Srm #define MAX_COMMIT_RETRIES 10
737c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */
747c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly
787c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the
797c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump.
807c478bd9Sstevel@tonic-gate */
817c478bd9Sstevel@tonic-gate #ifndef NDEBUG
827c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \
837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \
847c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \
857c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \
867c478bd9Sstevel@tonic-gate abort(); \
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate #else
897c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort()
907c478bd9Sstevel@tonic-gate #endif
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate struct restarter_event_handle {
937c478bd9Sstevel@tonic-gate char *reh_restarter_name;
947c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name;
957c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel;
967c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id;
977c478bd9Sstevel@tonic-gate char *reh_master_channel_name;
987c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel;
997c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id;
1007c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *);
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate struct restarter_event {
1047c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent;
1057c478bd9Sstevel@tonic-gate restarter_event_type_t re_type;
1067c478bd9Sstevel@tonic-gate char *re_instance_name;
1077c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle;
1087c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state;
1097c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state;
1107c478bd9Sstevel@tonic-gate };
1117c478bd9Sstevel@tonic-gate
112f6e214c7SGavin Maltby /*
113f6e214c7SGavin Maltby * Long reasons must all parse/read correctly in the following contexts:
114f6e214c7SGavin Maltby *
115f6e214c7SGavin Maltby * "A service instance transitioned state: %s."
116f6e214c7SGavin Maltby * "A service failed: %s."
117f6e214c7SGavin Maltby * "Reason: %s."
118f6e214c7SGavin Maltby * "The service transitioned state (%s) and ..."
119f6e214c7SGavin Maltby *
120f6e214c7SGavin Maltby * With the exception of restart_str_none they must also fit the following
121f6e214c7SGavin Maltby * moulds:
122f6e214c7SGavin Maltby *
123f6e214c7SGavin Maltby * "An instance transitioned because %s, and ..."
124f6e214c7SGavin Maltby * "An instance transitioned to <new-state> because %s, and ..."
125f6e214c7SGavin Maltby *
126f6e214c7SGavin Maltby * Note that whoever is rendering the long message must provide the
127f6e214c7SGavin Maltby * terminal punctuation - don't include it here. Similarly, do not
128f6e214c7SGavin Maltby * provide an initial capital letter in reason-long.
129f6e214c7SGavin Maltby *
130f6e214c7SGavin Maltby * The long reason strings are Volatile - within the grammatical constraints
131f6e214c7SGavin Maltby * above we may improve them as need be. The intention is that a consumer
132f6e214c7SGavin Maltby * may blindly render the string along the lines of the above examples,
133f6e214c7SGavin Maltby * but has no other guarantees as to the exact wording. Long reasons
134f6e214c7SGavin Maltby * are localized.
135f6e214c7SGavin Maltby *
136f6e214c7SGavin Maltby * We define revisions of the set of short reason strings in use. Within
137f6e214c7SGavin Maltby * a given revision, all short reasons are Committed. Consumers must check
138f6e214c7SGavin Maltby * the revision in use before relying on the semantics of the short reason
139f6e214c7SGavin Maltby * codes - if the version exceeds that which they are familiar with they should
140f6e214c7SGavin Maltby * fail gracefully. Having checked for version compatability, a consumer
141f6e214c7SGavin Maltby * is assured that
142f6e214c7SGavin Maltby *
143f6e214c7SGavin Maltby * "short_reason_A iff semantic_A", provided:
144f6e214c7SGavin Maltby *
145f6e214c7SGavin Maltby * . the restarter uses this short reason code at all,
146f6e214c7SGavin Maltby * . the short reason is not "none" (which a restarter could
147f6e214c7SGavin Maltby * specifiy for any transition semantics)
148f6e214c7SGavin Maltby *
149f6e214c7SGavin Maltby * To split/refine such a Committed semantic_A into further cases,
150f6e214c7SGavin Maltby * we are required to bump the revision number. This should be an
151f6e214c7SGavin Maltby * infrequent occurence. If you bump the revision number you may
152f6e214c7SGavin Maltby * need to make corresponding changes in any source that calls
153f6e214c7SGavin Maltby * restarter_str_version (e.g., FMA event generation).
154f6e214c7SGavin Maltby *
155f6e214c7SGavin Maltby * To add additional reasons to the set you must also bump the version
156f6e214c7SGavin Maltby * number.
157f6e214c7SGavin Maltby */
158f6e214c7SGavin Maltby
159f6e214c7SGavin Maltby /*
160f6e214c7SGavin Maltby * The following describes revision 0 of the set of transition reasons.
161f6e214c7SGavin Maltby * Read the preceding block comment before making any changes.
162f6e214c7SGavin Maltby */
163f6e214c7SGavin Maltby static const struct restarter_state_transition_reason restarter_str[] = {
164f6e214c7SGavin Maltby /*
165f6e214c7SGavin Maltby * Any transition for which the restarter has not provided a reason.
166f6e214c7SGavin Maltby */
167f6e214c7SGavin Maltby {
168f6e214c7SGavin Maltby restarter_str_none,
169f6e214c7SGavin Maltby "none",
170f6e214c7SGavin Maltby "the restarter gave no reason"
171f6e214c7SGavin Maltby },
172f6e214c7SGavin Maltby
173f6e214c7SGavin Maltby /*
174f6e214c7SGavin Maltby * A transition to maintenance state due to a
175f6e214c7SGavin Maltby * 'svcadm mark maintenance <fmri>'. *Not* used if the libscf
176f6e214c7SGavin Maltby * interface smf_maintain_instance(3SCF) is used to request maintenance.
177f6e214c7SGavin Maltby */
178f6e214c7SGavin Maltby {
179f6e214c7SGavin Maltby restarter_str_administrative_request,
180f6e214c7SGavin Maltby "administrative_request",
181f6e214c7SGavin Maltby "maintenance was requested by an administrator"
182f6e214c7SGavin Maltby },
183f6e214c7SGavin Maltby
184f6e214c7SGavin Maltby /*
185f6e214c7SGavin Maltby * A transition to maintenance state if a repository inconsistency
186f6e214c7SGavin Maltby * exists when the service/instance state is first read by startd
187f6e214c7SGavin Maltby * into the graph engine (this can also happen during startd restart).
188f6e214c7SGavin Maltby */
189f6e214c7SGavin Maltby {
190f6e214c7SGavin Maltby restarter_str_bad_repo_state,
191f6e214c7SGavin Maltby "bad_repo_state",
192f6e214c7SGavin Maltby "an SMF repository inconsistecy exists"
193f6e214c7SGavin Maltby },
194f6e214c7SGavin Maltby
195f6e214c7SGavin Maltby /*
196f6e214c7SGavin Maltby * A transition 'maintenance -> uninitialized' resulting always
197f6e214c7SGavin Maltby * from 'svcadm clear <fmri>'. *Not* used if the libscf interface
198f6e214c7SGavin Maltby * smf_restore_instance(3SCF) is used.
199f6e214c7SGavin Maltby */
200f6e214c7SGavin Maltby {
201f6e214c7SGavin Maltby restarter_str_clear_request,
202f6e214c7SGavin Maltby "clear_request",
203f6e214c7SGavin Maltby "maintenance clear was requested by an administrator"
204f6e214c7SGavin Maltby },
205f6e214c7SGavin Maltby
206f6e214c7SGavin Maltby /*
207f6e214c7SGavin Maltby * A transition 'online -> offline' due to a process core dump.
208f6e214c7SGavin Maltby */
209f6e214c7SGavin Maltby {
210f6e214c7SGavin Maltby restarter_str_ct_ev_core,
211f6e214c7SGavin Maltby "ct_ev_core",
212f6e214c7SGavin Maltby "a process dumped core"
213f6e214c7SGavin Maltby },
214f6e214c7SGavin Maltby
215f6e214c7SGavin Maltby /*
216f6e214c7SGavin Maltby * A transition 'online -> offline' due to an empty process contract,
217f6e214c7SGavin Maltby * i.e., the last process in a contract type service has exited.
218f6e214c7SGavin Maltby */
219f6e214c7SGavin Maltby {
220f6e214c7SGavin Maltby restarter_str_ct_ev_exit,
221f6e214c7SGavin Maltby "ct_ev_exit",
222f6e214c7SGavin Maltby "all processes in the service have exited"
223f6e214c7SGavin Maltby },
224f6e214c7SGavin Maltby
225f6e214c7SGavin Maltby /*
226f6e214c7SGavin Maltby * A transition 'online -> offline' due to a hardware error.
227f6e214c7SGavin Maltby */
228f6e214c7SGavin Maltby {
229f6e214c7SGavin Maltby restarter_str_ct_ev_hwerr,
230f6e214c7SGavin Maltby "ct_ev_hwerr",
231f6e214c7SGavin Maltby "a process was killed due to uncorrectable hardware error"
232f6e214c7SGavin Maltby },
233f6e214c7SGavin Maltby
234f6e214c7SGavin Maltby /*
235f6e214c7SGavin Maltby * A transition 'online -> offline' due to a process in the service
236f6e214c7SGavin Maltby * having received a fatal signal originating from outside the
237f6e214c7SGavin Maltby * service process contract.
238f6e214c7SGavin Maltby */
239f6e214c7SGavin Maltby {
240f6e214c7SGavin Maltby restarter_str_ct_ev_signal,
241f6e214c7SGavin Maltby "ct_ev_signal",
242f6e214c7SGavin Maltby "a process received a fatal signal from outside the service"
243f6e214c7SGavin Maltby },
244f6e214c7SGavin Maltby
245f6e214c7SGavin Maltby /*
246f6e214c7SGavin Maltby * A transition 'offline -> online' when all dependencies for the
247f6e214c7SGavin Maltby * service have been met.
248f6e214c7SGavin Maltby */
249f6e214c7SGavin Maltby {
250f6e214c7SGavin Maltby restarter_str_dependencies_satisfied,
251f6e214c7SGavin Maltby "dependencies_satisfied",
252f6e214c7SGavin Maltby "all dependencies have been satisfied"
253f6e214c7SGavin Maltby },
254f6e214c7SGavin Maltby
255f6e214c7SGavin Maltby /*
256f6e214c7SGavin Maltby * A transition 'online -> offline' because some dependency for the
257f6e214c7SGavin Maltby * service is no-longer met.
258f6e214c7SGavin Maltby */
259f6e214c7SGavin Maltby {
260f6e214c7SGavin Maltby restarter_str_dependency_activity,
261f6e214c7SGavin Maltby "dependency_activity",
262f6e214c7SGavin Maltby "a dependency activity required a stop"
263f6e214c7SGavin Maltby },
264f6e214c7SGavin Maltby
265f6e214c7SGavin Maltby /*
266f6e214c7SGavin Maltby * A transition to maintenance state due to a cycle in the
267f6e214c7SGavin Maltby * service dependencies.
268f6e214c7SGavin Maltby */
269f6e214c7SGavin Maltby {
270f6e214c7SGavin Maltby restarter_str_dependency_cycle,
271f6e214c7SGavin Maltby "dependency_cycle",
272f6e214c7SGavin Maltby "a dependency cycle exists"
273f6e214c7SGavin Maltby },
274f6e214c7SGavin Maltby
275f6e214c7SGavin Maltby /*
276f6e214c7SGavin Maltby * A transition 'online -> offline -> disabled' due to a
277f6e214c7SGavin Maltby * 'svcadm disable [-t] <fmri>' or smf_disable_instance(3SCF) call.
278f6e214c7SGavin Maltby */
279f6e214c7SGavin Maltby {
280f6e214c7SGavin Maltby restarter_str_disable_request,
281f6e214c7SGavin Maltby "disable_request",
282f6e214c7SGavin Maltby "a disable was requested"
283f6e214c7SGavin Maltby },
284f6e214c7SGavin Maltby
285f6e214c7SGavin Maltby /*
286f6e214c7SGavin Maltby * A transition 'disabled -> offline' due to a
287f6e214c7SGavin Maltby * 'svcadm enable [-t] <fmri>' or smf_enable_instance(3SCF) call.
288f6e214c7SGavin Maltby */
289f6e214c7SGavin Maltby {
290f6e214c7SGavin Maltby restarter_str_enable_request,
291f6e214c7SGavin Maltby "enable_request",
292f6e214c7SGavin Maltby "an enable was requested"
293f6e214c7SGavin Maltby },
294f6e214c7SGavin Maltby
295f6e214c7SGavin Maltby /*
296f6e214c7SGavin Maltby * A transition to maintenance state when a method fails
297f6e214c7SGavin Maltby * repeatedly for a retryable reason.
298f6e214c7SGavin Maltby */
299f6e214c7SGavin Maltby {
300f6e214c7SGavin Maltby restarter_str_fault_threshold_reached,
301f6e214c7SGavin Maltby "fault_threshold_reached",
302f6e214c7SGavin Maltby "a method is failing in a retryable manner but too often"
303f6e214c7SGavin Maltby },
304f6e214c7SGavin Maltby
305f6e214c7SGavin Maltby /*
306f6e214c7SGavin Maltby * A transition to uninitialized state when startd reads the service
307f6e214c7SGavin Maltby * configuration and inserts it into the graph engine.
308f6e214c7SGavin Maltby */
309f6e214c7SGavin Maltby {
310f6e214c7SGavin Maltby restarter_str_insert_in_graph,
311f6e214c7SGavin Maltby "insert_in_graph",
312f6e214c7SGavin Maltby "the instance was inserted in the graph"
313f6e214c7SGavin Maltby },
314f6e214c7SGavin Maltby
315f6e214c7SGavin Maltby /*
316f6e214c7SGavin Maltby * A transition to maintenance state due to an invalid dependency
317f6e214c7SGavin Maltby * declared for the service.
318f6e214c7SGavin Maltby */
319f6e214c7SGavin Maltby {
320f6e214c7SGavin Maltby restarter_str_invalid_dependency,
321f6e214c7SGavin Maltby "invalid_dependency",
322f6e214c7SGavin Maltby "a service has an invalid dependency"
323f6e214c7SGavin Maltby },
324f6e214c7SGavin Maltby
325f6e214c7SGavin Maltby /*
326f6e214c7SGavin Maltby * A transition to maintenance state because the service-declared
327f6e214c7SGavin Maltby * restarter is invalid.
328f6e214c7SGavin Maltby */
329f6e214c7SGavin Maltby {
330f6e214c7SGavin Maltby restarter_str_invalid_restarter,
331f6e214c7SGavin Maltby "invalid_restarter",
332f6e214c7SGavin Maltby "the service restarter is invalid"
333f6e214c7SGavin Maltby },
334f6e214c7SGavin Maltby
335f6e214c7SGavin Maltby /*
336f6e214c7SGavin Maltby * A transition to maintenance state because a restarter method
337f6e214c7SGavin Maltby * exited with one of SMF_EXIT_ERR_CONFIG, SMF_EXIT_ERR_NOSMF,
338f6e214c7SGavin Maltby * SMF_EXIT_ERR_PERM, or SMF_EXIT_ERR_FATAL.
339f6e214c7SGavin Maltby */
340f6e214c7SGavin Maltby {
341f6e214c7SGavin Maltby restarter_str_method_failed,
342f6e214c7SGavin Maltby "method_failed",
343f6e214c7SGavin Maltby "a start, stop or refresh method failed"
344f6e214c7SGavin Maltby },
345f6e214c7SGavin Maltby
346f6e214c7SGavin Maltby /*
347f6e214c7SGavin Maltby * A transition 'uninitialized -> {disabled|offline}' after
348f6e214c7SGavin Maltby * "insert_in_graph" to match the state configured in the
349f6e214c7SGavin Maltby * repository.
350f6e214c7SGavin Maltby */
351f6e214c7SGavin Maltby {
352f6e214c7SGavin Maltby restarter_str_per_configuration,
353f6e214c7SGavin Maltby "per_configuration",
354f6e214c7SGavin Maltby "the SMF repository configuration specifies this state"
355f6e214c7SGavin Maltby },
356f6e214c7SGavin Maltby
357f6e214c7SGavin Maltby /*
358f6e214c7SGavin Maltby * Refresh requested - no state change.
359f6e214c7SGavin Maltby */
360f6e214c7SGavin Maltby {
361f6e214c7SGavin Maltby restarter_str_refresh,
362f6e214c7SGavin Maltby NULL,
363f6e214c7SGavin Maltby "a refresh was requested (no change of state)"
364f6e214c7SGavin Maltby },
365f6e214c7SGavin Maltby
366f6e214c7SGavin Maltby /*
367f6e214c7SGavin Maltby * A transition 'online -> offline -> online' due to a
368f6e214c7SGavin Maltby * 'svcadm restart <fmri> or equivlaent libscf API call.
369f6e214c7SGavin Maltby * Both the 'online -> offline' and 'offline -> online' transtions
370f6e214c7SGavin Maltby * specify this reason.
371f6e214c7SGavin Maltby */
372f6e214c7SGavin Maltby {
373f6e214c7SGavin Maltby restarter_str_restart_request,
374f6e214c7SGavin Maltby "restart_request",
375f6e214c7SGavin Maltby "a restart was requested"
376f6e214c7SGavin Maltby },
377f6e214c7SGavin Maltby
378f6e214c7SGavin Maltby /*
379f6e214c7SGavin Maltby * A transition to maintenance state because the start method is
380f6e214c7SGavin Maltby * being executed successfully but too frequently.
381f6e214c7SGavin Maltby */
382f6e214c7SGavin Maltby {
383f6e214c7SGavin Maltby restarter_str_restarting_too_quickly,
384f6e214c7SGavin Maltby "restarting_too_quickly",
385f6e214c7SGavin Maltby "the instance is restarting too quickly"
386f6e214c7SGavin Maltby },
387f6e214c7SGavin Maltby
388f6e214c7SGavin Maltby /*
389f6e214c7SGavin Maltby * A transition to maintenance state due a service requesting
390f6e214c7SGavin Maltby * 'svcadm mark maintenance <fmri>' or equivalent libscf API call.
391f6e214c7SGavin Maltby * A command line 'svcadm mark maintenance <fmri>' does not produce
392f6e214c7SGavin Maltby * this reason - it produces administrative_request instead.
393f6e214c7SGavin Maltby */
394f6e214c7SGavin Maltby {
395f6e214c7SGavin Maltby restarter_str_service_request,
396f6e214c7SGavin Maltby "service_request",
397f6e214c7SGavin Maltby "maintenance was requested by another service"
398f6e214c7SGavin Maltby },
399f6e214c7SGavin Maltby
400f6e214c7SGavin Maltby /*
401f6e214c7SGavin Maltby * An instanced inserted into the graph at its existing state
402f6e214c7SGavin Maltby * during a startd restart - no state change.
403f6e214c7SGavin Maltby */
404f6e214c7SGavin Maltby {
405f6e214c7SGavin Maltby restarter_str_startd_restart,
406f6e214c7SGavin Maltby NULL,
407f6e214c7SGavin Maltby "the instance was inserted in the graph due to startd restart"
408f6e214c7SGavin Maltby }
409f6e214c7SGavin Maltby };
410f6e214c7SGavin Maltby
411f6e214c7SGavin Maltby uint32_t
restarter_str_version(void)412f6e214c7SGavin Maltby restarter_str_version(void)
413f6e214c7SGavin Maltby {
414f6e214c7SGavin Maltby return (RESTARTER_STRING_VERSION);
415f6e214c7SGavin Maltby }
416f6e214c7SGavin Maltby
417f6e214c7SGavin Maltby const char *
restarter_get_str_short(restarter_str_t key)418f6e214c7SGavin Maltby restarter_get_str_short(restarter_str_t key)
419f6e214c7SGavin Maltby {
420f6e214c7SGavin Maltby int i;
421f6e214c7SGavin Maltby for (i = 0; i < sizeof (restarter_str) /
422f6e214c7SGavin Maltby sizeof (struct restarter_state_transition_reason); i++)
423f6e214c7SGavin Maltby if (key == restarter_str[i].str_key)
424f6e214c7SGavin Maltby return (restarter_str[i].str_short);
425f6e214c7SGavin Maltby return (NULL);
426f6e214c7SGavin Maltby }
427f6e214c7SGavin Maltby
428f6e214c7SGavin Maltby const char *
restarter_get_str_long(restarter_str_t key)429f6e214c7SGavin Maltby restarter_get_str_long(restarter_str_t key)
430f6e214c7SGavin Maltby {
431f6e214c7SGavin Maltby int i;
432f6e214c7SGavin Maltby for (i = 0; i < sizeof (restarter_str) /
433f6e214c7SGavin Maltby sizeof (struct restarter_state_transition_reason); i++)
434f6e214c7SGavin Maltby if (key == restarter_str[i].str_key)
435f6e214c7SGavin Maltby return (dgettext(TEXT_DOMAIN,
436f6e214c7SGavin Maltby restarter_str[i].str_long));
437f6e214c7SGavin Maltby return (NULL);
438f6e214c7SGavin Maltby }
439f6e214c7SGavin Maltby
440870ad75aSSean Wilcox /*
441870ad75aSSean Wilcox * A static no memory error message mc_error_t structure
442870ad75aSSean Wilcox * to be used in cases when memory errors are to be returned
443870ad75aSSean Wilcox * This avoids the need to attempt to allocate memory for the
444870ad75aSSean Wilcox * message, therefore getting into a cycle of no memory failures.
445870ad75aSSean Wilcox */
446870ad75aSSean Wilcox mc_error_t mc_nomem_err = {
447870ad75aSSean Wilcox 0, ENOMEM, sizeof ("Out of memory") - 1, "Out of memory"
448870ad75aSSean Wilcox };
449870ad75aSSean Wilcox
4507c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n";
4517c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n";
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate int ndebug = 1;
4567c478bd9Sstevel@tonic-gate
457870ad75aSSean Wilcox /* PRINTFLIKE3 */
458870ad75aSSean Wilcox static mc_error_t *
mc_error_create(mc_error_t * e,int type,const char * format,...)459870ad75aSSean Wilcox mc_error_create(mc_error_t *e, int type, const char *format, ...)
460870ad75aSSean Wilcox {
461870ad75aSSean Wilcox mc_error_t *le;
462870ad75aSSean Wilcox va_list args;
463870ad75aSSean Wilcox int size;
464870ad75aSSean Wilcox
465870ad75aSSean Wilcox /*
466870ad75aSSean Wilcox * If the type is ENOMEM and format is NULL, then
467870ad75aSSean Wilcox * go ahead and return the default nomem error.
468870ad75aSSean Wilcox * Otherwise, attempt to allocate the memory and if
469870ad75aSSean Wilcox * that fails then there is no reason to continue.
470870ad75aSSean Wilcox */
471870ad75aSSean Wilcox if (type == ENOMEM && format == NULL)
472870ad75aSSean Wilcox return (&mc_nomem_err);
473870ad75aSSean Wilcox
474870ad75aSSean Wilcox if (e == NULL && (le = malloc(sizeof (mc_error_t))) == NULL)
475870ad75aSSean Wilcox return (&mc_nomem_err);
476870ad75aSSean Wilcox else
477870ad75aSSean Wilcox le = e;
478870ad75aSSean Wilcox
479870ad75aSSean Wilcox le->type = type;
480870ad75aSSean Wilcox le->destroy = 1;
481870ad75aSSean Wilcox va_start(args, format);
482870ad75aSSean Wilcox size = vsnprintf(NULL, 0, format, args) + 1;
483870ad75aSSean Wilcox if (size >= RESTARTER_ERRMSGSZ) {
484870ad75aSSean Wilcox if ((le = realloc(e, sizeof (mc_error_t) +
485870ad75aSSean Wilcox (size - RESTARTER_ERRMSGSZ))) == NULL) {
486870ad75aSSean Wilcox size = RESTARTER_ERRMSGSZ - 1;
487870ad75aSSean Wilcox le = e;
488870ad75aSSean Wilcox }
489870ad75aSSean Wilcox }
490870ad75aSSean Wilcox
491870ad75aSSean Wilcox le->size = size;
492870ad75aSSean Wilcox (void) vsnprintf(le->msg, le->size, format, args);
493870ad75aSSean Wilcox va_end(args);
494870ad75aSSean Wilcox
495870ad75aSSean Wilcox return (le);
496870ad75aSSean Wilcox }
497870ad75aSSean Wilcox
498870ad75aSSean Wilcox void
restarter_mc_error_destroy(mc_error_t * mc_err)499870ad75aSSean Wilcox restarter_mc_error_destroy(mc_error_t *mc_err)
500870ad75aSSean Wilcox {
501870ad75aSSean Wilcox if (mc_err == NULL)
502870ad75aSSean Wilcox return;
503870ad75aSSean Wilcox
504870ad75aSSean Wilcox /*
505870ad75aSSean Wilcox * If the error messages was allocated then free.
506870ad75aSSean Wilcox */
507870ad75aSSean Wilcox if (mc_err->destroy) {
508870ad75aSSean Wilcox free(mc_err);
509870ad75aSSean Wilcox }
510870ad75aSSean Wilcox }
511870ad75aSSean Wilcox
5127c478bd9Sstevel@tonic-gate static void
free_restarter_event_handle(struct restarter_event_handle * h)5137c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate if (h == NULL)
5167c478bd9Sstevel@tonic-gate return;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle,
5207c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter
5217c478bd9Sstevel@tonic-gate * restart.
5227c478bd9Sstevel@tonic-gate */
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL)
5257c478bd9Sstevel@tonic-gate free(h->reh_restarter_name);
5267c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL)
5277c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name);
5287c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL)
5297c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id);
5307c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL)
5317c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name);
5327c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL)
5337c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id);
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate free(h);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate char *
_restarter_get_channel_name(const char * fmri,int type)5397c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type)
5407c478bd9Sstevel@tonic-gate {
54113d8aaa1SSean Wilcox char *name;
5427c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN);
5437c478bd9Sstevel@tonic-gate char prefix_name[3];
54413d8aaa1SSean Wilcox int i;
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate if (chan_name == NULL)
5477c478bd9Sstevel@tonic-gate return (NULL);
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE)
5507c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_");
5517c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER)
5527c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_");
5537c478bd9Sstevel@tonic-gate else {
5547c478bd9Sstevel@tonic-gate free(chan_name);
5557c478bd9Sstevel@tonic-gate return (NULL);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate
55813d8aaa1SSean Wilcox /*
55913d8aaa1SSean Wilcox * Create a unique name
56013d8aaa1SSean Wilcox *
56113d8aaa1SSean Wilcox * Use the entire name, using a replacement of the /
56213d8aaa1SSean Wilcox * characters to get a better name.
56313d8aaa1SSean Wilcox *
56413d8aaa1SSean Wilcox * Remove the svc:/ from the beginning as this really
56513d8aaa1SSean Wilcox * isn't going to provide any uniqueness...
56613d8aaa1SSean Wilcox *
56713d8aaa1SSean Wilcox * An fmri name greater than MAX_CHNAME_LEN is going
56813d8aaa1SSean Wilcox * to be rejected as too long for the chan_name below
56913d8aaa1SSean Wilcox * in the snprintf call.
57013d8aaa1SSean Wilcox */
57113d8aaa1SSean Wilcox if ((name = strdup(strchr(fmri, '/') + 1)) == NULL) {
57213d8aaa1SSean Wilcox free(chan_name);
57313d8aaa1SSean Wilcox return (NULL);
57413d8aaa1SSean Wilcox }
57513d8aaa1SSean Wilcox i = 0;
57613d8aaa1SSean Wilcox while (name[i]) {
57713d8aaa1SSean Wilcox if (name[i] == '/') {
57813d8aaa1SSean Wilcox name[i] = '_';
57913d8aaa1SSean Wilcox }
58013d8aaa1SSean Wilcox
58113d8aaa1SSean Wilcox i++;
58213d8aaa1SSean Wilcox }
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,:
5867c478bd9Sstevel@tonic-gate */
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s",
5897c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) {
5907c478bd9Sstevel@tonic-gate free(chan_name);
59113d8aaa1SSean Wilcox chan_name = NULL;
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
59413d8aaa1SSean Wilcox free(name);
5957c478bd9Sstevel@tonic-gate return (chan_name);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate int
cb(sysevent_t * syse,void * cookie)5997c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie)
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie;
6027c478bd9Sstevel@tonic-gate restarter_event_t *e;
6037c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL;
6047c478bd9Sstevel@tonic-gate int ret = 0;
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t));
6077c478bd9Sstevel@tonic-gate if (e == NULL)
6087c478bd9Sstevel@tonic-gate uu_die(allocfail);
6097c478bd9Sstevel@tonic-gate e->re_event_handle = h;
6107c478bd9Sstevel@tonic-gate e->re_sysevent = syse;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0)
6137c478bd9Sstevel@tonic-gate uu_die(allocfail);
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE,
6167c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) ||
6177c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list,
6187c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) {
6197c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n",
6207c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse);
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate ret = 0;
6237c478bd9Sstevel@tonic-gate } else {
6247c478bd9Sstevel@tonic-gate ret = h->reh_handler(e);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate uu_free(e);
6287c478bd9Sstevel@tonic-gate nvlist_free(attr_list);
6297c478bd9Sstevel@tonic-gate return (ret);
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int,
6347c478bd9Sstevel@tonic-gate * restarter_event_handle_t **)
6357c478bd9Sstevel@tonic-gate *
6367c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel.
6377c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management.
6387c478bd9Sstevel@tonic-gate *
6397c478bd9Sstevel@tonic-gate * Returns 0 on success or
6407c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch
6417c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL
6427c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions
6437c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding
6447c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error
6457c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors
6467c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind()
6477c478bd9Sstevel@tonic-gate * EEXIST already subscribed
6487c478bd9Sstevel@tonic-gate */
6497c478bd9Sstevel@tonic-gate int
restarter_bind_handle(uint32_t version,const char * restarter_name,int (* event_handler)(restarter_event_t *),int flags,restarter_event_handle_t ** rehp)6507c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name,
6517c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags,
6527c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp)
6537c478bd9Sstevel@tonic-gate {
6547c478bd9Sstevel@tonic-gate restarter_event_handle_t *h;
6557c478bd9Sstevel@tonic-gate size_t sz;
6567c478bd9Sstevel@tonic-gate int err;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION)
6597c478bd9Sstevel@tonic-gate return (ENOTSUP);
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL)
6627c478bd9Sstevel@tonic-gate return (EINVAL);
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG)
6657c478bd9Sstevel@tonic-gate ndebug++;
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL)
6687c478bd9Sstevel@tonic-gate return (ENOMEM);
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN);
6717c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN);
6727c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name);
6737c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL ||
6747c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL ||
6757c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) {
6767c478bd9Sstevel@tonic-gate free_restarter_event_handle(h);
6777c478bd9Sstevel@tonic-gate return (ENOMEM);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN);
6817c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN);
6827c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN);
6837c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN);
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name =
6867c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name,
6877c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE);
6887c478bd9Sstevel@tonic-gate h->reh_master_channel_name =
6897c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name,
6907c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER);
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL ||
6937c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) {
6947c478bd9Sstevel@tonic-gate free_restarter_event_handle(h);
6957c478bd9Sstevel@tonic-gate return (ENOMEM);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name,
6997c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
7007c478bd9Sstevel@tonic-gate err = errno;
7017c478bd9Sstevel@tonic-gate assert(err != EINVAL);
7027c478bd9Sstevel@tonic-gate assert(err != ENOENT);
7037c478bd9Sstevel@tonic-gate free_restarter_event_handle(h);
7047c478bd9Sstevel@tonic-gate return (err);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name,
7087c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
7097c478bd9Sstevel@tonic-gate err = errno;
7107c478bd9Sstevel@tonic-gate assert(err != EINVAL);
7117c478bd9Sstevel@tonic-gate assert(err != ENOENT);
7127c478bd9Sstevel@tonic-gate free_restarter_event_handle(h);
7137c478bd9Sstevel@tonic-gate return (err);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate h->reh_handler = event_handler;
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1);
7197c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1);
7207c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1);
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel,
7237c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) {
7247c478bd9Sstevel@tonic-gate err = errno;
7257c478bd9Sstevel@tonic-gate assert(err != EINVAL);
7267c478bd9Sstevel@tonic-gate free_restarter_event_handle(h);
7277c478bd9Sstevel@tonic-gate return (err);
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate *rehp = h;
7317c478bd9Sstevel@tonic-gate return (0);
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate restarter_event_handle_t *
restarter_event_get_handle(restarter_event_t * e)7357c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL);
7387c478bd9Sstevel@tonic-gate return (e->re_event_handle);
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate restarter_event_type_t
restarter_event_get_type(restarter_event_t * e)7427c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e)
7437c478bd9Sstevel@tonic-gate {
7447c478bd9Sstevel@tonic-gate assert(e != NULL);
7457c478bd9Sstevel@tonic-gate return (e->re_type);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate ssize_t
restarter_event_get_instance(restarter_event_t * e,char * inst,size_t sz)7497c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL);
7527c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz));
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate int
restarter_event_get_current_states(restarter_event_t * e,restarter_instance_state_t * state,restarter_instance_state_t * next_state)7567c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e,
7577c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate if (e == NULL)
7607c478bd9Sstevel@tonic-gate return (-1);
7617c478bd9Sstevel@tonic-gate *state = e->re_state;
7627c478bd9Sstevel@tonic-gate *next_state = e->re_next_state;
7637c478bd9Sstevel@tonic-gate return (0);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate
7662c65c8b0Srm /*
7672c65c8b0Srm * restarter_event_publish_retry() is a wrapper around sysevent_evc_publish().
7682c65c8b0Srm * In case, the event cannot be sent at the first attempt (sysevent_evc_publish
7692c65c8b0Srm * returned EAGAIN - sysevent queue full), this function retries a few time
7702c65c8b0Srm * and return ENOSPC if it reaches the retry limit.
7712c65c8b0Srm *
7722c65c8b0Srm * The arguments to this function map the arguments of sysevent_evc_publish().
7732c65c8b0Srm *
7742c65c8b0Srm * On success, return 0. On error, return
7752c65c8b0Srm *
7762c65c8b0Srm * EFAULT - internal sysevent_evc_publish() error
7772c65c8b0Srm * ENOMEM - internal sysevent_evc_publish() error
7782c65c8b0Srm * EBADF - scp is invalid (sysevent_evc_publish() returned EINVAL)
7792c65c8b0Srm * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN)
7802c65c8b0Srm */
7812c65c8b0Srm int
restarter_event_publish_retry(evchan_t * scp,const char * class,const char * subclass,const char * vendor,const char * pub_name,nvlist_t * attr_list,uint32_t flags)7822c65c8b0Srm restarter_event_publish_retry(evchan_t *scp, const char *class,
7832c65c8b0Srm const char *subclass, const char *vendor, const char *pub_name,
7842c65c8b0Srm nvlist_t *attr_list, uint32_t flags)
7852c65c8b0Srm {
7862c65c8b0Srm int retries, ret;
7872c65c8b0Srm useconds_t retry_int = INITIAL_COMMIT_RETRY_INT;
7882c65c8b0Srm
7892c65c8b0Srm for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) {
7902c65c8b0Srm ret = sysevent_evc_publish(scp, class, subclass, vendor,
7912c65c8b0Srm pub_name, attr_list, flags);
7922c65c8b0Srm if (ret == 0)
7932c65c8b0Srm break;
7942c65c8b0Srm
7952c65c8b0Srm switch (ret) {
7962c65c8b0Srm case EAGAIN:
7972c65c8b0Srm /* Queue is full */
7982c65c8b0Srm (void) usleep(retry_int);
7992c65c8b0Srm
8002c65c8b0Srm retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT);
8012c65c8b0Srm break;
8022c65c8b0Srm
8032c65c8b0Srm case EINVAL:
8042c65c8b0Srm ret = EBADF;
8052c65c8b0Srm /* FALLTHROUGH */
8062c65c8b0Srm
8072c65c8b0Srm case EFAULT:
8082c65c8b0Srm case ENOMEM:
8092c65c8b0Srm return (ret);
8102c65c8b0Srm
8112c65c8b0Srm case EOVERFLOW:
8122c65c8b0Srm default:
8132c65c8b0Srm /* internal error - abort */
8142c65c8b0Srm bad_fail("sysevent_evc_publish", ret);
8152c65c8b0Srm }
8162c65c8b0Srm }
8172c65c8b0Srm
8182c65c8b0Srm if (retries == MAX_COMMIT_RETRIES)
8192c65c8b0Srm ret = ENOSPC;
8202c65c8b0Srm
8212c65c8b0Srm return (ret);
8222c65c8b0Srm }
8232c65c8b0Srm
8247c478bd9Sstevel@tonic-gate /*
8257c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository.
8267c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success,
8277c478bd9Sstevel@tonic-gate * return 0. On error, return
8287c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf
8297c478bd9Sstevel@tonic-gate * ENOMEM - out of memory
8307c478bd9Sstevel@tonic-gate * - repository server out of resources
8317c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running
8327c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken
8337c478bd9Sstevel@tonic-gate * - unknown libscf error
8347c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository
8357c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions
8367c478bd9Sstevel@tonic-gate * EACCESS - backend access denied
8377c478bd9Sstevel@tonic-gate * EROFS - backend is readonly
8387c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error
8397c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL)
8402c65c8b0Srm * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN)
8417c478bd9Sstevel@tonic-gate */
8427c478bd9Sstevel@tonic-gate int
restarter_set_states(restarter_event_handle_t * h,const char * inst,restarter_instance_state_t cur_state,restarter_instance_state_t new_cur_state,restarter_instance_state_t next_state,restarter_instance_state_t new_next_state,restarter_error_t e,restarter_str_t aux)8437c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst,
8447c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state,
8457c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state,
8467c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state,
8477c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e,
848f6e214c7SGavin Maltby restarter_str_t aux)
8497c478bd9Sstevel@tonic-gate {
8507c478bd9Sstevel@tonic-gate nvlist_t *attr;
8517c478bd9Sstevel@tonic-gate scf_handle_t *scf_h;
8527c478bd9Sstevel@tonic-gate instance_data_t id;
8537c478bd9Sstevel@tonic-gate int ret = 0;
854f6e214c7SGavin Maltby const char *p = restarter_get_str_short(aux);
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL);
8577c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL);
8587c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL);
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) {
8617c478bd9Sstevel@tonic-gate switch (scf_error()) {
8627c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH:
8637c478bd9Sstevel@tonic-gate return (EPROTO);
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY:
8667c478bd9Sstevel@tonic-gate return (ENOMEM);
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate default:
8697c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error());
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) {
8747c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h);
8757c478bd9Sstevel@tonic-gate switch (scf_error()) {
8767c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER:
8777c478bd9Sstevel@tonic-gate return (ENOTACTIVE);
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES:
8807c478bd9Sstevel@tonic-gate return (ENOMEM);
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
8837c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
8847c478bd9Sstevel@tonic-gate default:
8857c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error());
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 ||
8907c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 ||
8917c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state)
8927c478bd9Sstevel@tonic-gate != 0 ||
8937c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 ||
894f6e214c7SGavin Maltby nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0 ||
895f6e214c7SGavin Maltby nvlist_add_int32(attr, RESTARTER_NAME_REASON, aux) != 0) {
8967c478bd9Sstevel@tonic-gate ret = ENOMEM;
8972c65c8b0Srm } else {
8982c65c8b0Srm id.i_fmri = inst;
8992c65c8b0Srm id.i_state = cur_state;
9002c65c8b0Srm id.i_next_state = next_state;
9017c478bd9Sstevel@tonic-gate
9022c65c8b0Srm ret = _restarter_commit_states(scf_h, &id, new_cur_state,
903f6e214c7SGavin Maltby new_next_state, p);
9047c478bd9Sstevel@tonic-gate
9052c65c8b0Srm if (ret == 0) {
9062c65c8b0Srm ret = restarter_event_publish_retry(
9072c65c8b0Srm h->reh_master_channel, "master", "state_change",
9082c65c8b0Srm "com.sun", "librestart", attr, EVCH_NOSLEEP);
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate nvlist_free(attr);
9137c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h);
9147c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h);
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate return (ret);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate restarter_instance_state_t
restarter_string_to_state(char * string)9207c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string)
9217c478bd9Sstevel@tonic-gate {
9227c478bd9Sstevel@tonic-gate assert(string != NULL);
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0)
9257c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE);
9267c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0)
9277c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT);
9287c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0)
9297c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT);
9307c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0)
9317c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE);
9327c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0)
9337c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED);
9347c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0)
9357c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE);
9367c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0)
9377c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED);
9387c478bd9Sstevel@tonic-gate else {
9397c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE);
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate ssize_t
restarter_state_to_string(restarter_instance_state_t state,char * string,size_t len)9447c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string,
9457c478bd9Sstevel@tonic-gate size_t len)
9467c478bd9Sstevel@tonic-gate {
9477c478bd9Sstevel@tonic-gate assert(string != NULL);
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE)
9507c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len));
9517c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT)
9527c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len));
9537c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT)
9547c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len));
9557c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE)
9567c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE,
9577c478bd9Sstevel@tonic-gate len));
9587c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED)
9597c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED,
9607c478bd9Sstevel@tonic-gate len));
9617c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE)
9627c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len));
9637c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED)
9647c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED,
9657c478bd9Sstevel@tonic-gate len));
9667c478bd9Sstevel@tonic-gate else
9677c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len));
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate /*
9717c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is
9727c478bd9Sstevel@tonic-gate * added.
9737c478bd9Sstevel@tonic-gate *
9747c478bd9Sstevel@tonic-gate * Fails with
9757c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error
9767c478bd9Sstevel@tonic-gate * EBADF - inst is not set
9777c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted
9787c478bd9Sstevel@tonic-gate * EPERM - permission is denied
9797c478bd9Sstevel@tonic-gate * EACCES - backend denied access
9807c478bd9Sstevel@tonic-gate * EROFS - backend readonly
9817c478bd9Sstevel@tonic-gate */
9827c478bd9Sstevel@tonic-gate static int
instance_get_or_add_pg(scf_instance_t * inst,const char * name,const char * type,uint32_t flags,scf_propertygroup_t * pg)9837c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name,
9847c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate again:
9877c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0)
9887c478bd9Sstevel@tonic-gate return (0);
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate switch (scf_error()) {
9917c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
9927c478bd9Sstevel@tonic-gate default:
9937c478bd9Sstevel@tonic-gate return (ECONNABORTED);
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
9967c478bd9Sstevel@tonic-gate return (EBADF);
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
9997c478bd9Sstevel@tonic-gate return (ECANCELED);
10007c478bd9Sstevel@tonic-gate
10017c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
10027c478bd9Sstevel@tonic-gate break;
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
10057c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
10067c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error());
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate
10097c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0)
10107c478bd9Sstevel@tonic-gate return (0);
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate switch (scf_error()) {
10137c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10147c478bd9Sstevel@tonic-gate default:
10157c478bd9Sstevel@tonic-gate return (ECONNABORTED);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
10187c478bd9Sstevel@tonic-gate return (ECANCELED);
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
10217c478bd9Sstevel@tonic-gate goto again;
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
10247c478bd9Sstevel@tonic-gate return (EPERM);
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
10277c478bd9Sstevel@tonic-gate return (EACCES);
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
10307c478bd9Sstevel@tonic-gate return (EROFS);
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
10337c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
10347c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */
10357c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error());
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate return (0);
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate /*
10427c478bd9Sstevel@tonic-gate * Fails with
10437c478bd9Sstevel@tonic-gate * ECONNABORTED
10447c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted
10457c478bd9Sstevel@tonic-gate */
10467c478bd9Sstevel@tonic-gate static int
tx_set_value(scf_transaction_t * tx,scf_transaction_entry_t * ent,const char * pname,scf_type_t ty,scf_value_t * val)10477c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent,
10487c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val)
10497c478bd9Sstevel@tonic-gate {
10507c478bd9Sstevel@tonic-gate int r;
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate for (;;) {
10537c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname,
10547c478bd9Sstevel@tonic-gate ty) == 0)
10557c478bd9Sstevel@tonic-gate break;
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate switch (scf_error()) {
10587c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10597c478bd9Sstevel@tonic-gate default:
10607c478bd9Sstevel@tonic-gate return (ECONNABORTED);
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
10637c478bd9Sstevel@tonic-gate return (ECANCELED);
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
10667c478bd9Sstevel@tonic-gate break;
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
10697c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
10707c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
10717c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
10727c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type",
10737c478bd9Sstevel@tonic-gate scf_error());
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0)
10777c478bd9Sstevel@tonic-gate break;
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate switch (scf_error()) {
10807c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
10817c478bd9Sstevel@tonic-gate default:
10827c478bd9Sstevel@tonic-gate return (ECONNABORTED);
10837c478bd9Sstevel@tonic-gate
10847c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
10857c478bd9Sstevel@tonic-gate return (ECANCELED);
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
10887c478bd9Sstevel@tonic-gate break;
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
10917c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
10927c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
10937c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
10947c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error());
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate
10987c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val);
10997c478bd9Sstevel@tonic-gate assert(r == 0);
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate return (0);
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate /*
11057c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If
11067c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0.
11077c478bd9Sstevel@tonic-gate * Fails with
11087c478bd9Sstevel@tonic-gate * ENOMEM - out of memory
11097c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken
11107c478bd9Sstevel@tonic-gate * - unknown libscf error
11117c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI
11127c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist
11137c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions
11147c478bd9Sstevel@tonic-gate * EACCES - backend access denied
11157c478bd9Sstevel@tonic-gate * EROFS - backend is readonly
11167c478bd9Sstevel@tonic-gate */
11177c478bd9Sstevel@tonic-gate int
_restarter_commit_states(scf_handle_t * h,instance_data_t * id,restarter_instance_state_t new_state,restarter_instance_state_t new_state_next,const char * aux)11187c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id,
11197c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state,
11207c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux)
11217c478bd9Sstevel@tonic-gate {
11227c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ];
11237c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ];
11247c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ];
11257c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ];
11267c478bd9Sstevel@tonic-gate int ret = 0, r;
11277c478bd9Sstevel@tonic-gate struct timeval now;
11287c478bd9Sstevel@tonic-gate ssize_t sz;
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL;
11317c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL;
11327c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL;
11337c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL;
11347c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL;
11357c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL;
11367c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE);
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL ||
11417c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL ||
11427c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL ||
11437c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL ||
11447c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL ||
11457c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL ||
11467c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL ||
11477c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL ||
11487c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL ||
11497c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL ||
11507c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) {
11517c478bd9Sstevel@tonic-gate ret = ENOMEM;
11527c478bd9Sstevel@tonic-gate goto out;
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state,
11567c478bd9Sstevel@tonic-gate sizeof (str_new_state));
11577c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state));
11587c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next,
11597c478bd9Sstevel@tonic-gate sizeof (str_new_state_next));
11607c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next));
11617c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state,
11627c478bd9Sstevel@tonic-gate sizeof (str_state));
11637c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state));
11647c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next,
11657c478bd9Sstevel@tonic-gate sizeof (str_state_next));
11667c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next));
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL);
11697c478bd9Sstevel@tonic-gate assert(ret != -1);
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst,
11727c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) {
11737c478bd9Sstevel@tonic-gate switch (scf_error()) {
11747c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
11757c478bd9Sstevel@tonic-gate default:
11767c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
11777c478bd9Sstevel@tonic-gate break;
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
11807c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED:
11817c478bd9Sstevel@tonic-gate ret = EINVAL;
11827c478bd9Sstevel@tonic-gate break;
11837c478bd9Sstevel@tonic-gate
11847c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
11857c478bd9Sstevel@tonic-gate ret = ENOENT;
11867c478bd9Sstevel@tonic-gate break;
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
11897c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error());
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate goto out;
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate
11957c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 ||
1196eb1a3463STruong Nguyen scf_value_set_astring(v_state_next, str_new_state_next) != 0)
11977c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error());
11987c478bd9Sstevel@tonic-gate
1199eb1a3463STruong Nguyen if (aux) {
1200eb1a3463STruong Nguyen if (scf_value_set_astring(v_aux, aux) != 0)
1201eb1a3463STruong Nguyen bad_fail("scf_value_set_astring", scf_error());
1202eb1a3463STruong Nguyen }
1203eb1a3463STruong Nguyen
12047c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0)
12057c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error());
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate add_pg:
12087c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
12097c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) {
12107c478bd9Sstevel@tonic-gate case 0:
12117c478bd9Sstevel@tonic-gate break;
12127c478bd9Sstevel@tonic-gate
12137c478bd9Sstevel@tonic-gate case ECONNABORTED:
12147c478bd9Sstevel@tonic-gate case EPERM:
12157c478bd9Sstevel@tonic-gate case EACCES:
12167c478bd9Sstevel@tonic-gate case EROFS:
12177c478bd9Sstevel@tonic-gate ret = r;
12187c478bd9Sstevel@tonic-gate goto out;
12197c478bd9Sstevel@tonic-gate
12207c478bd9Sstevel@tonic-gate case ECANCELED:
12217c478bd9Sstevel@tonic-gate ret = ENOENT;
12227c478bd9Sstevel@tonic-gate goto out;
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate case EBADF:
12257c478bd9Sstevel@tonic-gate default:
12267c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r);
12277c478bd9Sstevel@tonic-gate }
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate for (;;) {
12307c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) {
12317c478bd9Sstevel@tonic-gate switch (scf_error()) {
12327c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
12337c478bd9Sstevel@tonic-gate default:
12347c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
12357c478bd9Sstevel@tonic-gate goto out;
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
12387c478bd9Sstevel@tonic-gate goto add_pg;
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
12417c478bd9Sstevel@tonic-gate ret = EPERM;
12427c478bd9Sstevel@tonic-gate goto out;
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
12457c478bd9Sstevel@tonic-gate ret = EACCES;
12467c478bd9Sstevel@tonic-gate goto out;
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
12497c478bd9Sstevel@tonic-gate ret = EROFS;
12507c478bd9Sstevel@tonic-gate goto out;
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
12537c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
12547c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error());
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate }
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE,
12597c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 ||
12607c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE,
12617c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 ||
12627c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP,
12637c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) {
12647c478bd9Sstevel@tonic-gate switch (r) {
12657c478bd9Sstevel@tonic-gate case ECONNABORTED:
12667c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
12677c478bd9Sstevel@tonic-gate goto out;
12687c478bd9Sstevel@tonic-gate
12697c478bd9Sstevel@tonic-gate case ECANCELED:
12707c478bd9Sstevel@tonic-gate scf_transaction_reset(t);
12717c478bd9Sstevel@tonic-gate goto add_pg;
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate default:
12747c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r);
12757c478bd9Sstevel@tonic-gate }
12767c478bd9Sstevel@tonic-gate }
12777c478bd9Sstevel@tonic-gate
1278eb1a3463STruong Nguyen if (aux) {
1279eb1a3463STruong Nguyen if ((r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE,
1280eb1a3463STruong Nguyen SCF_TYPE_ASTRING, v_aux)) != 0) {
1281eb1a3463STruong Nguyen switch (r) {
1282eb1a3463STruong Nguyen case ECONNABORTED:
1283eb1a3463STruong Nguyen ret = ECONNABORTED;
1284eb1a3463STruong Nguyen goto out;
1285eb1a3463STruong Nguyen
1286eb1a3463STruong Nguyen case ECANCELED:
1287eb1a3463STruong Nguyen scf_transaction_reset(t);
1288eb1a3463STruong Nguyen goto add_pg;
1289eb1a3463STruong Nguyen
1290eb1a3463STruong Nguyen default:
1291eb1a3463STruong Nguyen bad_fail("tx_set_value", r);
1292eb1a3463STruong Nguyen }
1293eb1a3463STruong Nguyen }
1294eb1a3463STruong Nguyen }
1295eb1a3463STruong Nguyen
12967c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t);
12977c478bd9Sstevel@tonic-gate if (ret == 1)
12987c478bd9Sstevel@tonic-gate break;
12997c478bd9Sstevel@tonic-gate if (ret == -1) {
13007c478bd9Sstevel@tonic-gate switch (scf_error()) {
13017c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
13027c478bd9Sstevel@tonic-gate default:
13037c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
13047c478bd9Sstevel@tonic-gate goto out;
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
13077c478bd9Sstevel@tonic-gate ret = EPERM;
13087c478bd9Sstevel@tonic-gate goto out;
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
13117c478bd9Sstevel@tonic-gate ret = EACCES;
13127c478bd9Sstevel@tonic-gate goto out;
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
13157c478bd9Sstevel@tonic-gate ret = EROFS;
13167c478bd9Sstevel@tonic-gate goto out;
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
13197c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error());
13207c478bd9Sstevel@tonic-gate }
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate scf_transaction_reset(t);
13247c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) {
13257c478bd9Sstevel@tonic-gate switch (scf_error()) {
13267c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
13277c478bd9Sstevel@tonic-gate default:
13287c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
13297c478bd9Sstevel@tonic-gate goto out;
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
13327c478bd9Sstevel@tonic-gate goto add_pg;
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate }
13357c478bd9Sstevel@tonic-gate }
13367c478bd9Sstevel@tonic-gate
13377c478bd9Sstevel@tonic-gate id->i_state = new_state;
13387c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next;
13397c478bd9Sstevel@tonic-gate ret = 0;
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate out:
13427c478bd9Sstevel@tonic-gate scf_transaction_destroy(t);
13437c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state);
13447c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next);
13457c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime);
13467c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux);
13477c478bd9Sstevel@tonic-gate scf_value_destroy(v_state);
13487c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next);
13497c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime);
13507c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux);
13517c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
13527c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst);
13537c478bd9Sstevel@tonic-gate
13547c478bd9Sstevel@tonic-gate return (ret);
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /*
13587c478bd9Sstevel@tonic-gate * Fails with
13597c478bd9Sstevel@tonic-gate * EINVAL - type is invalid
13607c478bd9Sstevel@tonic-gate * ENOMEM
13617c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken
13627c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set
13637c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted
13647c478bd9Sstevel@tonic-gate * EPERM - permission denied
13657c478bd9Sstevel@tonic-gate * EACCES - backend access denied
13667c478bd9Sstevel@tonic-gate * EROFS - backend readonly
13677c478bd9Sstevel@tonic-gate */
13687c478bd9Sstevel@tonic-gate int
restarter_remove_contract(scf_instance_t * s_inst,ctid_t contract_id,restarter_contract_type_t type)13697c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id,
13707c478bd9Sstevel@tonic-gate restarter_contract_type_t type)
13717c478bd9Sstevel@tonic-gate {
13727c478bd9Sstevel@tonic-gate scf_handle_t *h;
13737c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL;
13747c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL;
13757c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
13767c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL;
13777c478bd9Sstevel@tonic-gate scf_value_t *val;
13787c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL;
13797c478bd9Sstevel@tonic-gate const char *pname;
13807c478bd9Sstevel@tonic-gate int ret = 0, primary;
13817c478bd9Sstevel@tonic-gate uint64_t c;
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate switch (type) {
13847c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY:
13857c478bd9Sstevel@tonic-gate primary = 1;
13867c478bd9Sstevel@tonic-gate break;
13877c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT:
13887c478bd9Sstevel@tonic-gate primary = 0;
13897c478bd9Sstevel@tonic-gate break;
13907c478bd9Sstevel@tonic-gate default:
13917c478bd9Sstevel@tonic-gate return (EINVAL);
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate
13947c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst);
13957c478bd9Sstevel@tonic-gate
13967c478bd9Sstevel@tonic-gate pg = scf_pg_create(h);
13977c478bd9Sstevel@tonic-gate prop = scf_property_create(h);
13987c478bd9Sstevel@tonic-gate iter = scf_iter_create(h);
13997c478bd9Sstevel@tonic-gate t = scf_transaction_create(h);
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) {
14027c478bd9Sstevel@tonic-gate ret = ENOMEM;
14037c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate add:
14077c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
14087c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
14097c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg);
14107c478bd9Sstevel@tonic-gate if (ret != 0)
14117c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT :
14147c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT;
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate for (;;) {
14177c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) {
14187c478bd9Sstevel@tonic-gate switch (scf_error()) {
14197c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
14207c478bd9Sstevel@tonic-gate default:
14217c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
14227c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14237c478bd9Sstevel@tonic-gate
14247c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
14257c478bd9Sstevel@tonic-gate goto add;
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
14287c478bd9Sstevel@tonic-gate ret = EPERM;
14297c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
14327c478bd9Sstevel@tonic-gate ret = EACCES;
14337c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
14367c478bd9Sstevel@tonic-gate ret = EROFS;
14377c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
14407c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
14417c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
14427c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error());
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate
14467c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h);
14477c478bd9Sstevel@tonic-gate
14487c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) {
14497c478bd9Sstevel@tonic-gate replace:
14507c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid,
14517c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) {
14527c478bd9Sstevel@tonic-gate switch (scf_error()) {
14537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
14547c478bd9Sstevel@tonic-gate default:
14557c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
14567c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14577c478bd9Sstevel@tonic-gate
14587c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
14597c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
14607c478bd9Sstevel@tonic-gate goto add;
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
14637c478bd9Sstevel@tonic-gate goto new;
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
14667c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
14677c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
14687c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
14697c478bd9Sstevel@tonic-gate bad_fail(
14707c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype",
14717c478bd9Sstevel@tonic-gate scf_error());
14727c478bd9Sstevel@tonic-gate }
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate
14757c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) {
14767c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) {
14777c478bd9Sstevel@tonic-gate switch (scf_error()) {
14787c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
14797c478bd9Sstevel@tonic-gate default:
14807c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
14817c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14827c478bd9Sstevel@tonic-gate
14837c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
14847c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
14857c478bd9Sstevel@tonic-gate bad_fail(
14867c478bd9Sstevel@tonic-gate "scf_iter_property_values",
14877c478bd9Sstevel@tonic-gate scf_error());
14887c478bd9Sstevel@tonic-gate }
14897c478bd9Sstevel@tonic-gate }
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gate next_val:
14927c478bd9Sstevel@tonic-gate val = scf_value_create(h);
14937c478bd9Sstevel@tonic-gate if (val == NULL) {
14947c478bd9Sstevel@tonic-gate assert(scf_error() ==
14957c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY);
14967c478bd9Sstevel@tonic-gate ret = ENOMEM;
14977c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate
15007c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val);
15017c478bd9Sstevel@tonic-gate if (ret == -1) {
15027c478bd9Sstevel@tonic-gate switch (scf_error()) {
15037c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
15047c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
15057c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
15087c478bd9Sstevel@tonic-gate scf_value_destroy(val);
15097c478bd9Sstevel@tonic-gate goto add;
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
15127c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
15133eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED:
15147c478bd9Sstevel@tonic-gate default:
15157c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value",
15167c478bd9Sstevel@tonic-gate scf_error());
15177c478bd9Sstevel@tonic-gate }
15187c478bd9Sstevel@tonic-gate }
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate if (ret == 1) {
15217c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c);
15227c478bd9Sstevel@tonic-gate assert(ret == 0);
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate if (c != contract_id) {
15257c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid,
15267c478bd9Sstevel@tonic-gate val);
15277c478bd9Sstevel@tonic-gate assert(ret == 0);
15287c478bd9Sstevel@tonic-gate } else {
15297c478bd9Sstevel@tonic-gate scf_value_destroy(val);
15307c478bd9Sstevel@tonic-gate }
15317c478bd9Sstevel@tonic-gate
15327c478bd9Sstevel@tonic-gate goto next_val;
15337c478bd9Sstevel@tonic-gate }
15347c478bd9Sstevel@tonic-gate
15357c478bd9Sstevel@tonic-gate scf_value_destroy(val);
15367c478bd9Sstevel@tonic-gate } else {
15377c478bd9Sstevel@tonic-gate switch (scf_error()) {
15387c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
15397c478bd9Sstevel@tonic-gate default:
15407c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
15417c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH:
15447c478bd9Sstevel@tonic-gate break;
15457c478bd9Sstevel@tonic-gate
15467c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
15477c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
15487c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type",
15497c478bd9Sstevel@tonic-gate scf_error());
15507c478bd9Sstevel@tonic-gate }
15517c478bd9Sstevel@tonic-gate }
15527c478bd9Sstevel@tonic-gate } else {
15537c478bd9Sstevel@tonic-gate switch (scf_error()) {
15547c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
15557c478bd9Sstevel@tonic-gate default:
15567c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
15577c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
15587c478bd9Sstevel@tonic-gate
15597c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
15607c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
15617c478bd9Sstevel@tonic-gate goto add;
15627c478bd9Sstevel@tonic-gate
15637c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
15647c478bd9Sstevel@tonic-gate break;
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
15677c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
15687c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
15697c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error());
15707c478bd9Sstevel@tonic-gate }
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate new:
15737c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname,
15747c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) {
15757c478bd9Sstevel@tonic-gate switch (scf_error()) {
15767c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
15777c478bd9Sstevel@tonic-gate default:
15787c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
15797c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
15827c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
15837c478bd9Sstevel@tonic-gate goto add;
15847c478bd9Sstevel@tonic-gate
15857c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
15867c478bd9Sstevel@tonic-gate goto replace;
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
15897c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
15907c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
15917c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new",
15927c478bd9Sstevel@tonic-gate scf_error());
15937c478bd9Sstevel@tonic-gate }
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate }
15967c478bd9Sstevel@tonic-gate
15977c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t);
15987c478bd9Sstevel@tonic-gate if (ret == -1) {
15997c478bd9Sstevel@tonic-gate switch (scf_error()) {
16007c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
16017c478bd9Sstevel@tonic-gate default:
16027c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
16037c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
16067c478bd9Sstevel@tonic-gate goto add;
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
16097c478bd9Sstevel@tonic-gate ret = EPERM;
16107c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
16137c478bd9Sstevel@tonic-gate ret = EACCES;
16147c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
16157c478bd9Sstevel@tonic-gate
16167c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
16177c478bd9Sstevel@tonic-gate ret = EROFS;
16187c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
16217c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error());
16227c478bd9Sstevel@tonic-gate }
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate if (ret == 1) {
16257c478bd9Sstevel@tonic-gate ret = 0;
16267c478bd9Sstevel@tonic-gate break;
16277c478bd9Sstevel@tonic-gate }
16287c478bd9Sstevel@tonic-gate
16297c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
16307c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) {
16317c478bd9Sstevel@tonic-gate switch (scf_error()) {
16327c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
16337c478bd9Sstevel@tonic-gate default:
16347c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
16357c478bd9Sstevel@tonic-gate goto remove_contract_cleanup;
16367c478bd9Sstevel@tonic-gate
16377c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
16387c478bd9Sstevel@tonic-gate goto add;
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
16417c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error());
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate }
16447c478bd9Sstevel@tonic-gate }
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate remove_contract_cleanup:
16477c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
16487c478bd9Sstevel@tonic-gate scf_transaction_destroy(t);
16497c478bd9Sstevel@tonic-gate scf_iter_destroy(iter);
16507c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
16517c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate return (ret);
16547c478bd9Sstevel@tonic-gate }
16557c478bd9Sstevel@tonic-gate
16567c478bd9Sstevel@tonic-gate /*
16577c478bd9Sstevel@tonic-gate * Fails with
16587c478bd9Sstevel@tonic-gate * EINVAL - type is invalid
16597c478bd9Sstevel@tonic-gate * ENOMEM
16607c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection
16617c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set
16627c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted
16637c478bd9Sstevel@tonic-gate * EPERM
16647c478bd9Sstevel@tonic-gate * EACCES
16657c478bd9Sstevel@tonic-gate * EROFS
16667c478bd9Sstevel@tonic-gate */
16677c478bd9Sstevel@tonic-gate int
restarter_store_contract(scf_instance_t * s_inst,ctid_t contract_id,restarter_contract_type_t type)16687c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id,
16697c478bd9Sstevel@tonic-gate restarter_contract_type_t type)
16707c478bd9Sstevel@tonic-gate {
16717c478bd9Sstevel@tonic-gate scf_handle_t *h;
16727c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL;
16737c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL;
16747c478bd9Sstevel@tonic-gate scf_value_t *val;
16757c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
16767c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL;
16777c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL;
16787c478bd9Sstevel@tonic-gate const char *pname;
16797c478bd9Sstevel@tonic-gate int ret = 0, primary;
16807c478bd9Sstevel@tonic-gate
16817c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY)
16827c478bd9Sstevel@tonic-gate primary = 1;
16837c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT)
16847c478bd9Sstevel@tonic-gate primary = 0;
16857c478bd9Sstevel@tonic-gate else
16867c478bd9Sstevel@tonic-gate return (EINVAL);
16877c478bd9Sstevel@tonic-gate
16887c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst);
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate pg = scf_pg_create(h);
16917c478bd9Sstevel@tonic-gate prop = scf_property_create(h);
16927c478bd9Sstevel@tonic-gate iter = scf_iter_create(h);
16937c478bd9Sstevel@tonic-gate t = scf_transaction_create(h);
16947c478bd9Sstevel@tonic-gate
16957c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) {
16967c478bd9Sstevel@tonic-gate ret = ENOMEM;
16977c478bd9Sstevel@tonic-gate goto out;
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate
17007c478bd9Sstevel@tonic-gate add:
17017c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
17027c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
17037c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg);
17047c478bd9Sstevel@tonic-gate if (ret != 0)
17057c478bd9Sstevel@tonic-gate goto out;
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT :
17087c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT;
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate for (;;) {
17117c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) {
17127c478bd9Sstevel@tonic-gate switch (scf_error()) {
17137c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
17147c478bd9Sstevel@tonic-gate default:
17157c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
17167c478bd9Sstevel@tonic-gate goto out;
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
17197c478bd9Sstevel@tonic-gate goto add;
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
17227c478bd9Sstevel@tonic-gate ret = EPERM;
17237c478bd9Sstevel@tonic-gate goto out;
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
17267c478bd9Sstevel@tonic-gate ret = EACCES;
17277c478bd9Sstevel@tonic-gate goto out;
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
17307c478bd9Sstevel@tonic-gate ret = EROFS;
17317c478bd9Sstevel@tonic-gate goto out;
17327c478bd9Sstevel@tonic-gate
17337c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
17347c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
17357c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
17367c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error());
17377c478bd9Sstevel@tonic-gate }
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h);
17417c478bd9Sstevel@tonic-gate if (t_cid == NULL) {
17427c478bd9Sstevel@tonic-gate ret = ENOMEM;
17437c478bd9Sstevel@tonic-gate goto out;
17447c478bd9Sstevel@tonic-gate }
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) {
17477c478bd9Sstevel@tonic-gate replace:
17487c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid,
17497c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) {
17507c478bd9Sstevel@tonic-gate switch (scf_error()) {
17517c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
17527c478bd9Sstevel@tonic-gate default:
17537c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
17547c478bd9Sstevel@tonic-gate goto out;
17557c478bd9Sstevel@tonic-gate
17567c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
17577c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
17587c478bd9Sstevel@tonic-gate goto add;
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
17617c478bd9Sstevel@tonic-gate goto new;
17627c478bd9Sstevel@tonic-gate
17637c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
17647c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
17657c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE:
17667c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
17677c478bd9Sstevel@tonic-gate bad_fail(
17687c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type",
17697c478bd9Sstevel@tonic-gate scf_error());
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) {
17747c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) {
17757c478bd9Sstevel@tonic-gate switch (scf_error()) {
17767c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
17777c478bd9Sstevel@tonic-gate default:
17787c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
17797c478bd9Sstevel@tonic-gate goto out;
17807c478bd9Sstevel@tonic-gate
17817c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
17827c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
17837c478bd9Sstevel@tonic-gate bad_fail(
17847c478bd9Sstevel@tonic-gate "scf_iter_property_values",
17857c478bd9Sstevel@tonic-gate scf_error());
17867c478bd9Sstevel@tonic-gate }
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate next_val:
17907c478bd9Sstevel@tonic-gate val = scf_value_create(h);
17917c478bd9Sstevel@tonic-gate if (val == NULL) {
17927c478bd9Sstevel@tonic-gate assert(scf_error() ==
17937c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY);
17947c478bd9Sstevel@tonic-gate ret = ENOMEM;
17957c478bd9Sstevel@tonic-gate goto out;
17967c478bd9Sstevel@tonic-gate }
17977c478bd9Sstevel@tonic-gate
17987c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val);
17997c478bd9Sstevel@tonic-gate if (ret == -1) {
18007c478bd9Sstevel@tonic-gate switch (scf_error()) {
18017c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
18027c478bd9Sstevel@tonic-gate default:
18037c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
18047c478bd9Sstevel@tonic-gate goto out;
18057c478bd9Sstevel@tonic-gate
18067c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
18077c478bd9Sstevel@tonic-gate scf_value_destroy(val);
18087c478bd9Sstevel@tonic-gate goto add;
18097c478bd9Sstevel@tonic-gate
18107c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
18117c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
18123eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED:
18137c478bd9Sstevel@tonic-gate bad_fail(
18147c478bd9Sstevel@tonic-gate "scf_iter_next_value",
18157c478bd9Sstevel@tonic-gate scf_error());
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate }
18187c478bd9Sstevel@tonic-gate
18197c478bd9Sstevel@tonic-gate if (ret == 1) {
18207c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val);
18217c478bd9Sstevel@tonic-gate assert(ret == 0);
18227c478bd9Sstevel@tonic-gate
18237c478bd9Sstevel@tonic-gate goto next_val;
18247c478bd9Sstevel@tonic-gate }
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate scf_value_destroy(val);
18277c478bd9Sstevel@tonic-gate } else {
18287c478bd9Sstevel@tonic-gate switch (scf_error()) {
18297c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
18307c478bd9Sstevel@tonic-gate default:
18317c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
18327c478bd9Sstevel@tonic-gate goto out;
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH:
18357c478bd9Sstevel@tonic-gate break;
18367c478bd9Sstevel@tonic-gate
18377c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
18387c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
18397c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type",
18407c478bd9Sstevel@tonic-gate scf_error());
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate }
18437c478bd9Sstevel@tonic-gate } else {
18447c478bd9Sstevel@tonic-gate switch (scf_error()) {
18457c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
18467c478bd9Sstevel@tonic-gate default:
18477c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
18487c478bd9Sstevel@tonic-gate goto out;
18497c478bd9Sstevel@tonic-gate
18507c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
18517c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
18527c478bd9Sstevel@tonic-gate goto add;
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
18557c478bd9Sstevel@tonic-gate break;
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
18587c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
18597c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
18607c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error());
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate new:
18647c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname,
18657c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) {
18667c478bd9Sstevel@tonic-gate switch (scf_error()) {
18677c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
18687c478bd9Sstevel@tonic-gate default:
18697c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
18707c478bd9Sstevel@tonic-gate goto out;
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
18737c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid);
18747c478bd9Sstevel@tonic-gate goto add;
18757c478bd9Sstevel@tonic-gate
18767c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS:
18777c478bd9Sstevel@tonic-gate goto replace;
18787c478bd9Sstevel@tonic-gate
18797c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
18807c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
18817c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
18827c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new",
18837c478bd9Sstevel@tonic-gate scf_error());
18847c478bd9Sstevel@tonic-gate }
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate }
18877c478bd9Sstevel@tonic-gate
18887c478bd9Sstevel@tonic-gate val = scf_value_create(h);
18897c478bd9Sstevel@tonic-gate if (val == NULL) {
18907c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY);
18917c478bd9Sstevel@tonic-gate ret = ENOMEM;
18927c478bd9Sstevel@tonic-gate goto out;
18937c478bd9Sstevel@tonic-gate }
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id);
18967c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val);
18977c478bd9Sstevel@tonic-gate assert(ret == 0);
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t);
19007c478bd9Sstevel@tonic-gate if (ret == -1) {
19017c478bd9Sstevel@tonic-gate switch (scf_error()) {
19027c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
19037c478bd9Sstevel@tonic-gate default:
19047c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
19057c478bd9Sstevel@tonic-gate goto out;
19067c478bd9Sstevel@tonic-gate
19077c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
19087c478bd9Sstevel@tonic-gate goto add;
19097c478bd9Sstevel@tonic-gate
19107c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED:
19117c478bd9Sstevel@tonic-gate ret = EPERM;
19127c478bd9Sstevel@tonic-gate goto out;
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS:
19157c478bd9Sstevel@tonic-gate ret = EACCES;
19167c478bd9Sstevel@tonic-gate goto out;
19177c478bd9Sstevel@tonic-gate
19187c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY:
19197c478bd9Sstevel@tonic-gate ret = EROFS;
19207c478bd9Sstevel@tonic-gate goto out;
19217c478bd9Sstevel@tonic-gate
19227c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
19237c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error());
19247c478bd9Sstevel@tonic-gate }
19257c478bd9Sstevel@tonic-gate }
19267c478bd9Sstevel@tonic-gate if (ret == 1) {
19277c478bd9Sstevel@tonic-gate ret = 0;
19287c478bd9Sstevel@tonic-gate break;
19297c478bd9Sstevel@tonic-gate }
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
19327c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) {
19337c478bd9Sstevel@tonic-gate switch (scf_error()) {
19347c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
19357c478bd9Sstevel@tonic-gate default:
19367c478bd9Sstevel@tonic-gate ret = ECONNABORTED;
19377c478bd9Sstevel@tonic-gate goto out;
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
19407c478bd9Sstevel@tonic-gate goto add;
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
19437c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error());
19447c478bd9Sstevel@tonic-gate }
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate }
19477c478bd9Sstevel@tonic-gate
19487c478bd9Sstevel@tonic-gate out:
19497c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t);
19507c478bd9Sstevel@tonic-gate scf_transaction_destroy(t);
19517c478bd9Sstevel@tonic-gate scf_iter_destroy(iter);
19527c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
19537c478bd9Sstevel@tonic-gate scf_pg_destroy(pg);
19547c478bd9Sstevel@tonic-gate
19557c478bd9Sstevel@tonic-gate return (ret);
19567c478bd9Sstevel@tonic-gate }
19577c478bd9Sstevel@tonic-gate
19587c478bd9Sstevel@tonic-gate int
restarter_rm_libs_loadable()19597c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable()
19607c478bd9Sstevel@tonic-gate {
19617c478bd9Sstevel@tonic-gate void *libhndl;
19627c478bd9Sstevel@tonic-gate
19637c478bd9Sstevel@tonic-gate if (method_context_safety)
19647c478bd9Sstevel@tonic-gate return (1);
19657c478bd9Sstevel@tonic-gate
19667c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL)
19677c478bd9Sstevel@tonic-gate return (0);
19687c478bd9Sstevel@tonic-gate
19697c478bd9Sstevel@tonic-gate (void) dlclose(libhndl);
19707c478bd9Sstevel@tonic-gate
19717c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL)
19727c478bd9Sstevel@tonic-gate return (0);
19737c478bd9Sstevel@tonic-gate
19747c478bd9Sstevel@tonic-gate (void) dlclose(libhndl);
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate method_context_safety = 1;
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate return (1);
19797c478bd9Sstevel@tonic-gate }
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate static int
get_astring_val(scf_propertygroup_t * pg,const char * name,char * buf,size_t bufsz,scf_property_t * prop,scf_value_t * val)19827c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf,
19837c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val)
19847c478bd9Sstevel@tonic-gate {
19857c478bd9Sstevel@tonic-gate ssize_t szret;
19867c478bd9Sstevel@tonic-gate
198713d8aaa1SSean Wilcox if (pg == NULL)
198813d8aaa1SSean Wilcox return (-1);
198913d8aaa1SSean Wilcox
19907c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) {
19917c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
19927c478bd9Sstevel@tonic-gate uu_die(rcbroken);
19937c478bd9Sstevel@tonic-gate return (-1);
19947c478bd9Sstevel@tonic-gate }
19957c478bd9Sstevel@tonic-gate
19967c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
19977c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
19987c478bd9Sstevel@tonic-gate uu_die(rcbroken);
19997c478bd9Sstevel@tonic-gate return (-1);
20007c478bd9Sstevel@tonic-gate }
20017c478bd9Sstevel@tonic-gate
20027c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz);
20037c478bd9Sstevel@tonic-gate
20047c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1);
20057c478bd9Sstevel@tonic-gate }
20067c478bd9Sstevel@tonic-gate
2007eb1a3463STruong Nguyen static int
get_boolean_val(scf_propertygroup_t * pg,const char * name,uint8_t * b,scf_property_t * prop,scf_value_t * val)2008eb1a3463STruong Nguyen get_boolean_val(scf_propertygroup_t *pg, const char *name, uint8_t *b,
2009eb1a3463STruong Nguyen scf_property_t *prop, scf_value_t *val)
2010eb1a3463STruong Nguyen {
2011eb1a3463STruong Nguyen if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) {
2012eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
2013eb1a3463STruong Nguyen uu_die(rcbroken);
2014eb1a3463STruong Nguyen return (-1);
2015eb1a3463STruong Nguyen }
2016eb1a3463STruong Nguyen
2017eb1a3463STruong Nguyen if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2018eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
2019eb1a3463STruong Nguyen uu_die(rcbroken);
2020eb1a3463STruong Nguyen return (-1);
2021eb1a3463STruong Nguyen }
2022eb1a3463STruong Nguyen
2023eb1a3463STruong Nguyen if (scf_value_get_boolean(val, b))
2024eb1a3463STruong Nguyen return (-1);
2025eb1a3463STruong Nguyen
2026eb1a3463STruong Nguyen return (0);
2027eb1a3463STruong Nguyen }
2028eb1a3463STruong Nguyen
20297c478bd9Sstevel@tonic-gate /*
20307c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already.
20317c478bd9Sstevel@tonic-gate * Fails with
20327c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed
20337c478bd9Sstevel@tonic-gate * ENOENT - no entry found
20347c478bd9Sstevel@tonic-gate * EIO - I/O error
20357c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors
20367c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles
20377c478bd9Sstevel@tonic-gate */
20387c478bd9Sstevel@tonic-gate static int
lookup_pwd(struct method_context * mcp)20397c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp)
20407c478bd9Sstevel@tonic-gate {
20417c478bd9Sstevel@tonic-gate struct passwd *pwdp;
20427c478bd9Sstevel@tonic-gate
20437c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid)
20447c478bd9Sstevel@tonic-gate return (0);
20457c478bd9Sstevel@tonic-gate
20467c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) {
20477c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX);
20487c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0);
20497c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz);
20507c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL)
20517c478bd9Sstevel@tonic-gate return (ENOMEM);
20527c478bd9Sstevel@tonic-gate }
20537c478bd9Sstevel@tonic-gate
20547c478bd9Sstevel@tonic-gate do {
20557c478bd9Sstevel@tonic-gate errno = 0;
20567c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf,
20577c478bd9Sstevel@tonic-gate mcp->pwbufsz);
20587c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR);
20597c478bd9Sstevel@tonic-gate if (pwdp != NULL)
20607c478bd9Sstevel@tonic-gate return (0);
20617c478bd9Sstevel@tonic-gate
20627c478bd9Sstevel@tonic-gate free(mcp->pwbuf);
20637c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL;
20647c478bd9Sstevel@tonic-gate
20657c478bd9Sstevel@tonic-gate switch (errno) {
20667c478bd9Sstevel@tonic-gate case 0:
20677c478bd9Sstevel@tonic-gate default:
20687c478bd9Sstevel@tonic-gate /*
20697c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with
20707c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the
20717c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown
20727c478bd9Sstevel@tonic-gate * errors.
20737c478bd9Sstevel@tonic-gate */
20747c478bd9Sstevel@tonic-gate return (ENOENT);
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate case EIO:
20777c478bd9Sstevel@tonic-gate case EMFILE:
20787c478bd9Sstevel@tonic-gate case ENFILE:
20797c478bd9Sstevel@tonic-gate return (errno);
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate case ERANGE:
20827c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno);
20837c478bd9Sstevel@tonic-gate /* NOTREACHED */
20847c478bd9Sstevel@tonic-gate }
20857c478bd9Sstevel@tonic-gate }
20867c478bd9Sstevel@tonic-gate
20877c478bd9Sstevel@tonic-gate /*
20887c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or
20897c478bd9Sstevel@tonic-gate * ERANGE the uid is too big
20907c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid
20917c478bd9Sstevel@tonic-gate * ENOMEM out of memory
20927c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str
20937c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred
20947c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors
20957c478bd9Sstevel@tonic-gate */
20967c478bd9Sstevel@tonic-gate int
get_uid(const char * str,struct method_context * ci,uid_t * uidp)20977c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp)
20987c478bd9Sstevel@tonic-gate {
20997c478bd9Sstevel@tonic-gate if (isdigit(str[0])) {
21007c478bd9Sstevel@tonic-gate uid_t uid;
21017c478bd9Sstevel@tonic-gate char *cp;
21027c478bd9Sstevel@tonic-gate
21037c478bd9Sstevel@tonic-gate errno = 0;
21047c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10);
21057c478bd9Sstevel@tonic-gate
21067c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) {
21077c478bd9Sstevel@tonic-gate assert(errno != EINVAL);
21087c478bd9Sstevel@tonic-gate return (errno);
21097c478bd9Sstevel@tonic-gate }
21107c478bd9Sstevel@tonic-gate
21117c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp)
21127c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t')
21137c478bd9Sstevel@tonic-gate return (EINVAL);
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate if (uid > UID_MAX)
21167c478bd9Sstevel@tonic-gate return (EINVAL);
21177c478bd9Sstevel@tonic-gate
21187c478bd9Sstevel@tonic-gate *uidp = uid;
21197c478bd9Sstevel@tonic-gate return (0);
21207c478bd9Sstevel@tonic-gate } else {
21217c478bd9Sstevel@tonic-gate struct passwd *pwdp;
21227c478bd9Sstevel@tonic-gate
21237c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) {
21247c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX);
21257c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz);
21267c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL)
21277c478bd9Sstevel@tonic-gate return (ENOMEM);
21287c478bd9Sstevel@tonic-gate }
21297c478bd9Sstevel@tonic-gate
21307c478bd9Sstevel@tonic-gate do {
21317c478bd9Sstevel@tonic-gate errno = 0;
21327c478bd9Sstevel@tonic-gate pwdp =
21337c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz);
21347c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR);
21357c478bd9Sstevel@tonic-gate
21367c478bd9Sstevel@tonic-gate if (pwdp != NULL) {
21377c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid;
21387c478bd9Sstevel@tonic-gate return (0);
21397c478bd9Sstevel@tonic-gate } else {
21407c478bd9Sstevel@tonic-gate free(ci->pwbuf);
21417c478bd9Sstevel@tonic-gate ci->pwbuf = NULL;
21427c478bd9Sstevel@tonic-gate switch (errno) {
21437c478bd9Sstevel@tonic-gate case 0:
21447c478bd9Sstevel@tonic-gate return (ENOENT);
21457c478bd9Sstevel@tonic-gate
21467c478bd9Sstevel@tonic-gate case ENOENT:
21477c478bd9Sstevel@tonic-gate case EIO:
21487c478bd9Sstevel@tonic-gate case EMFILE:
21497c478bd9Sstevel@tonic-gate case ENFILE:
21507c478bd9Sstevel@tonic-gate return (errno);
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate case ERANGE:
21537c478bd9Sstevel@tonic-gate default:
21547c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno);
21557c478bd9Sstevel@tonic-gate /* NOTREACHED */
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate }
21587c478bd9Sstevel@tonic-gate }
21597c478bd9Sstevel@tonic-gate }
21607c478bd9Sstevel@tonic-gate
21617c478bd9Sstevel@tonic-gate gid_t
get_gid(const char * str)21627c478bd9Sstevel@tonic-gate get_gid(const char *str)
21637c478bd9Sstevel@tonic-gate {
21647c478bd9Sstevel@tonic-gate if (isdigit(str[0])) {
21657c478bd9Sstevel@tonic-gate gid_t gid;
21667c478bd9Sstevel@tonic-gate char *cp;
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate errno = 0;
21697c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10);
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0)
2172f48205beScasper return ((gid_t)-1);
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp)
21757c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t')
2176f48205beScasper return ((gid_t)-1);
21777c478bd9Sstevel@tonic-gate
21787c478bd9Sstevel@tonic-gate return (gid);
21797c478bd9Sstevel@tonic-gate } else {
21807c478bd9Sstevel@tonic-gate struct group grp, *ret;
21817c478bd9Sstevel@tonic-gate char *buffer;
21827c478bd9Sstevel@tonic-gate size_t buflen;
21837c478bd9Sstevel@tonic-gate
21847c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
21857c478bd9Sstevel@tonic-gate buffer = malloc(buflen);
21867c478bd9Sstevel@tonic-gate if (buffer == NULL)
21877c478bd9Sstevel@tonic-gate uu_die(allocfail);
21887c478bd9Sstevel@tonic-gate
21897c478bd9Sstevel@tonic-gate errno = 0;
21907c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen);
21917c478bd9Sstevel@tonic-gate free(buffer);
21927c478bd9Sstevel@tonic-gate
2193f48205beScasper return (ret == NULL ? (gid_t)-1 : grp.gr_gid);
21947c478bd9Sstevel@tonic-gate }
21957c478bd9Sstevel@tonic-gate }
21967c478bd9Sstevel@tonic-gate
21977c478bd9Sstevel@tonic-gate /*
21987c478bd9Sstevel@tonic-gate * Fails with
21997c478bd9Sstevel@tonic-gate * ENOMEM - out of memory
22007c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry
22017c478bd9Sstevel@tonic-gate * no project entry
22027c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred
22037c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors
22047c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles
22057c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range
22067c478bd9Sstevel@tonic-gate * EINVAL - str is invalid
22077c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big
22087c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured
22097c478bd9Sstevel@tonic-gate */
22107c478bd9Sstevel@tonic-gate int
get_projid(const char * str,struct method_context * cip)22117c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip)
22127c478bd9Sstevel@tonic-gate {
22137c478bd9Sstevel@tonic-gate int ret;
22147c478bd9Sstevel@tonic-gate void *buf;
22157c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ;
22167c478bd9Sstevel@tonic-gate struct project proj, *pp;
22177c478bd9Sstevel@tonic-gate
22187c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) {
22197c478bd9Sstevel@tonic-gate if (cip->uid == 0) {
22207c478bd9Sstevel@tonic-gate /* Don't change project for root services */
22217c478bd9Sstevel@tonic-gate cip->project = NULL;
22227c478bd9Sstevel@tonic-gate return (0);
22237c478bd9Sstevel@tonic-gate }
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) {
22267c478bd9Sstevel@tonic-gate case 0:
22277c478bd9Sstevel@tonic-gate break;
22287c478bd9Sstevel@tonic-gate
22297c478bd9Sstevel@tonic-gate case ENOMEM:
22307c478bd9Sstevel@tonic-gate case ENOENT:
22317c478bd9Sstevel@tonic-gate case EIO:
22327c478bd9Sstevel@tonic-gate case EMFILE:
22337c478bd9Sstevel@tonic-gate case ENFILE:
22347c478bd9Sstevel@tonic-gate return (ret);
22357c478bd9Sstevel@tonic-gate
22367c478bd9Sstevel@tonic-gate default:
22377c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret);
22387c478bd9Sstevel@tonic-gate }
22397c478bd9Sstevel@tonic-gate
22407c478bd9Sstevel@tonic-gate buf = malloc(bufsz);
22417c478bd9Sstevel@tonic-gate if (buf == NULL)
22427c478bd9Sstevel@tonic-gate return (ENOMEM);
22437c478bd9Sstevel@tonic-gate
22447c478bd9Sstevel@tonic-gate do {
22457c478bd9Sstevel@tonic-gate errno = 0;
22467c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf,
22477c478bd9Sstevel@tonic-gate bufsz);
22487c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR);
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate /* to be continued ... */
22517c478bd9Sstevel@tonic-gate } else {
22527c478bd9Sstevel@tonic-gate projid_t projid;
22537c478bd9Sstevel@tonic-gate char *cp;
22547c478bd9Sstevel@tonic-gate
22557c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) {
22567c478bd9Sstevel@tonic-gate cip->project = strdup(str);
22577c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM);
22587c478bd9Sstevel@tonic-gate }
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate errno = 0;
22617c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10);
22627c478bd9Sstevel@tonic-gate
22637c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) {
22647c478bd9Sstevel@tonic-gate assert(errno == ERANGE);
22657c478bd9Sstevel@tonic-gate return (errno);
22667c478bd9Sstevel@tonic-gate }
22677c478bd9Sstevel@tonic-gate
22687c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp)
22697c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t')
22707c478bd9Sstevel@tonic-gate return (EINVAL);
22717c478bd9Sstevel@tonic-gate
22727c478bd9Sstevel@tonic-gate if (projid > MAXPROJID)
22737c478bd9Sstevel@tonic-gate return (ERANGE);
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate buf = malloc(bufsz);
22767c478bd9Sstevel@tonic-gate if (buf == NULL)
22777c478bd9Sstevel@tonic-gate return (ENOMEM);
22787c478bd9Sstevel@tonic-gate
22797c478bd9Sstevel@tonic-gate do {
22807c478bd9Sstevel@tonic-gate errno = 0;
22817c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz);
22827c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR);
22837c478bd9Sstevel@tonic-gate }
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate if (pp) {
22867c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name);
22877c478bd9Sstevel@tonic-gate free(buf);
22887c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM);
22897c478bd9Sstevel@tonic-gate }
22907c478bd9Sstevel@tonic-gate
22917c478bd9Sstevel@tonic-gate free(buf);
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate switch (errno) {
22947c478bd9Sstevel@tonic-gate case 0:
22957c478bd9Sstevel@tonic-gate return (ENOENT);
22967c478bd9Sstevel@tonic-gate
22977c478bd9Sstevel@tonic-gate case EIO:
22987c478bd9Sstevel@tonic-gate case EMFILE:
22997c478bd9Sstevel@tonic-gate case ENFILE:
23007c478bd9Sstevel@tonic-gate return (errno);
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate case ERANGE:
23037c478bd9Sstevel@tonic-gate return (E2BIG);
23047c478bd9Sstevel@tonic-gate
23057c478bd9Sstevel@tonic-gate default:
23067c478bd9Sstevel@tonic-gate return (-1);
23077c478bd9Sstevel@tonic-gate }
23087c478bd9Sstevel@tonic-gate }
23097c478bd9Sstevel@tonic-gate
23107c478bd9Sstevel@tonic-gate /*
23117c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns
23127c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has
23137c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success.
23147c478bd9Sstevel@tonic-gate */
23157c478bd9Sstevel@tonic-gate int
get_groups(char * str,struct method_context * ci)23167c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci)
23177c478bd9Sstevel@tonic-gate {
23187c478bd9Sstevel@tonic-gate char *cp, *end, *next;
23197c478bd9Sstevel@tonic-gate uint_t i;
23207c478bd9Sstevel@tonic-gate
23217c478bd9Sstevel@tonic-gate const char * const whitespace = " \t";
23227c478bd9Sstevel@tonic-gate const char * const illegal = ", \t";
23237c478bd9Sstevel@tonic-gate
23247c478bd9Sstevel@tonic-gate if (str[0] == '\0') {
23257c478bd9Sstevel@tonic-gate ci->ngroups = 0;
23267c478bd9Sstevel@tonic-gate return (0);
23277c478bd9Sstevel@tonic-gate }
23287c478bd9Sstevel@tonic-gate
23297c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) {
23307c478bd9Sstevel@tonic-gate /* skip whitespace */
23317c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace);
23327c478bd9Sstevel@tonic-gate
23337c478bd9Sstevel@tonic-gate /* find the end */
23347c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal);
23357c478bd9Sstevel@tonic-gate
23367c478bd9Sstevel@tonic-gate /* skip whitespace after end */
23377c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace);
23387c478bd9Sstevel@tonic-gate
23397c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */
23407c478bd9Sstevel@tonic-gate if (*next == ',')
23417c478bd9Sstevel@tonic-gate ++next;
23427c478bd9Sstevel@tonic-gate
23437c478bd9Sstevel@tonic-gate *end = '\0';
23447c478bd9Sstevel@tonic-gate
2345f48205beScasper if ((ci->groups[i] = get_gid(cp)) == (gid_t)-1) {
23467c478bd9Sstevel@tonic-gate ci->ngroups = 0;
23477c478bd9Sstevel@tonic-gate return (EINVAL);
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate
23507c478bd9Sstevel@tonic-gate ++i;
23517c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) {
23527c478bd9Sstevel@tonic-gate ci->ngroups = 0;
23537c478bd9Sstevel@tonic-gate return (E2BIG);
23547c478bd9Sstevel@tonic-gate }
23557c478bd9Sstevel@tonic-gate
23567c478bd9Sstevel@tonic-gate cp = next;
23577c478bd9Sstevel@tonic-gate }
23587c478bd9Sstevel@tonic-gate
23597c478bd9Sstevel@tonic-gate ci->ngroups = i;
23607c478bd9Sstevel@tonic-gate return (0);
23617c478bd9Sstevel@tonic-gate }
23627c478bd9Sstevel@tonic-gate
2363870ad75aSSean Wilcox
23647c478bd9Sstevel@tonic-gate /*
2365870ad75aSSean Wilcox * Return an error message structure containing the error message
2366870ad75aSSean Wilcox * with context, and the error so the caller can make a decision
2367870ad75aSSean Wilcox * on what to do next.
2368870ad75aSSean Wilcox *
2369870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can
2370870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer
2371870ad75aSSean Wilcox * in case it was reallocated.
23727c478bd9Sstevel@tonic-gate */
2373870ad75aSSean Wilcox static mc_error_t *
get_profile(scf_propertygroup_t * methpg,scf_propertygroup_t * instpg,scf_property_t * prop,scf_value_t * val,const char * cmdline,struct method_context * ci,mc_error_t * merr)237413d8aaa1SSean Wilcox get_profile(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg,
237513d8aaa1SSean Wilcox scf_property_t *prop, scf_value_t *val, const char *cmdline,
2376870ad75aSSean Wilcox struct method_context *ci, mc_error_t *merr)
23777c478bd9Sstevel@tonic-gate {
23787c478bd9Sstevel@tonic-gate char *buf = ci->vbuf;
23797c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz;
23807c478bd9Sstevel@tonic-gate char cmd[PATH_MAX];
23817c478bd9Sstevel@tonic-gate char *cp, *value;
23827c478bd9Sstevel@tonic-gate const char *cmdp;
23837c478bd9Sstevel@tonic-gate execattr_t *eap;
2384870ad75aSSean Wilcox mc_error_t *err = merr;
2385870ad75aSSean Wilcox int r;
23867c478bd9Sstevel@tonic-gate
238713d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop,
238813d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PROFILE, buf,
238913d8aaa1SSean Wilcox buf_sz, prop, val) == 0))
2390870ad75aSSean Wilcox return (mc_error_create(merr, scf_error(),
2391870ad75aSSean Wilcox "Method context requires a profile, but the \"%s\" "
2392870ad75aSSean Wilcox "property could not be read. scf_error is %s",
2393870ad75aSSean Wilcox SCF_PROPERTY_PROFILE, scf_strerror(scf_error())));
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */
23967c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t");
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate if (cp == NULL) {
23997c478bd9Sstevel@tonic-gate cmdp = cmdline;
24007c478bd9Sstevel@tonic-gate } else {
24017c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline);
24027c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0';
24037c478bd9Sstevel@tonic-gate cmdp = cmd;
24047c478bd9Sstevel@tonic-gate }
24057c478bd9Sstevel@tonic-gate
24067c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */
24077c478bd9Sstevel@tonic-gate
24087c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE);
24097c478bd9Sstevel@tonic-gate if (eap == NULL)
2410870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2411870ad75aSSean Wilcox "Could not find the execution profile \"%s\", "
2412870ad75aSSean Wilcox "command %s.", buf, cmdp));
24137c478bd9Sstevel@tonic-gate
24147c478bd9Sstevel@tonic-gate /* Based on pfexec.c */
24157c478bd9Sstevel@tonic-gate
24167c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */
24177c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) {
2418870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->euid)) != 0) {
2419f48205beScasper ci->euid = (uid_t)-1;
2420870ad75aSSean Wilcox err = mc_error_create(merr, r,
2421870ad75aSSean Wilcox "Could not interpret profile euid value \"%s\", "
2422870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.",
2423870ad75aSSean Wilcox value, buf, r);
24247c478bd9Sstevel@tonic-gate goto out;
24257c478bd9Sstevel@tonic-gate }
24267c478bd9Sstevel@tonic-gate }
24277c478bd9Sstevel@tonic-gate
24287c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) {
2429870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->uid)) != 0) {
2430f48205beScasper ci->euid = ci->uid = (uid_t)-1;
2431870ad75aSSean Wilcox err = mc_error_create(merr, r,
2432870ad75aSSean Wilcox "Could not interpret profile uid value \"%s\", "
2433870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.",
2434870ad75aSSean Wilcox value, buf, r);
24357c478bd9Sstevel@tonic-gate goto out;
24367c478bd9Sstevel@tonic-gate }
24377c478bd9Sstevel@tonic-gate ci->euid = ci->uid;
24387c478bd9Sstevel@tonic-gate }
24397c478bd9Sstevel@tonic-gate
24407c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) {
24417c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value);
2442f48205beScasper if (ci->gid == (gid_t)-1) {
2443870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL,
2444870ad75aSSean Wilcox "Could not interpret profile gid value \"%s\", "
2445870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf);
24467c478bd9Sstevel@tonic-gate goto out;
24477c478bd9Sstevel@tonic-gate }
24487c478bd9Sstevel@tonic-gate }
24497c478bd9Sstevel@tonic-gate
24507c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) {
24517c478bd9Sstevel@tonic-gate ci->egid = get_gid(value);
2452f48205beScasper if (ci->egid == (gid_t)-1) {
2453870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL,
2454870ad75aSSean Wilcox "Could not interpret profile egid value \"%s\", "
2455870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf);
24567c478bd9Sstevel@tonic-gate goto out;
24577c478bd9Sstevel@tonic-gate }
24587c478bd9Sstevel@tonic-gate }
24597c478bd9Sstevel@tonic-gate
24607c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) {
24617c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL);
24627c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) {
24637c478bd9Sstevel@tonic-gate if (errno != EINVAL)
2464870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM,
2465870ad75aSSean Wilcox ALLOCFAIL);
24667c478bd9Sstevel@tonic-gate else
2467870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL,
2468870ad75aSSean Wilcox "Could not interpret profile "
2469870ad75aSSean Wilcox "limitprivs value \"%s\", from "
2470870ad75aSSean Wilcox "the execution profile \"%s\".",
2471870ad75aSSean Wilcox value, buf);
24727c478bd9Sstevel@tonic-gate goto out;
24737c478bd9Sstevel@tonic-gate }
24747c478bd9Sstevel@tonic-gate }
24757c478bd9Sstevel@tonic-gate
24767c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) {
24777c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL);
24787c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) {
24797c478bd9Sstevel@tonic-gate if (errno != EINVAL)
2480870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM,
2481870ad75aSSean Wilcox ALLOCFAIL);
24827c478bd9Sstevel@tonic-gate else
2483870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL,
2484870ad75aSSean Wilcox "Could not interpret profile privs value "
2485870ad75aSSean Wilcox "\"%s\", from the execution profile "
2486870ad75aSSean Wilcox "\"%s\".", value, buf);
24877c478bd9Sstevel@tonic-gate goto out;
24887c478bd9Sstevel@tonic-gate }
24897c478bd9Sstevel@tonic-gate }
24907c478bd9Sstevel@tonic-gate
24917c478bd9Sstevel@tonic-gate out:
24927c478bd9Sstevel@tonic-gate free_execattr(eap);
24937c478bd9Sstevel@tonic-gate
2494870ad75aSSean Wilcox return (err);
24957c478bd9Sstevel@tonic-gate }
24967c478bd9Sstevel@tonic-gate
24977c478bd9Sstevel@tonic-gate /*
2498870ad75aSSean Wilcox * Return an error message structure containing the error message
2499870ad75aSSean Wilcox * with context, and the error so the caller can make a decision
2500870ad75aSSean Wilcox * on what to do next.
2501870ad75aSSean Wilcox *
2502870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can
2503870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer
2504870ad75aSSean Wilcox * in case it was reallocated.
25057c478bd9Sstevel@tonic-gate */
2506870ad75aSSean Wilcox static mc_error_t *
get_ids(scf_propertygroup_t * methpg,scf_propertygroup_t * instpg,scf_property_t * prop,scf_value_t * val,struct method_context * ci,mc_error_t * merr)250713d8aaa1SSean Wilcox get_ids(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg,
2508870ad75aSSean Wilcox scf_property_t *prop, scf_value_t *val, struct method_context *ci,
2509870ad75aSSean Wilcox mc_error_t *merr)
25107c478bd9Sstevel@tonic-gate {
25117c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf;
25127c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz;
25137c478bd9Sstevel@tonic-gate int r;
25147c478bd9Sstevel@tonic-gate
251513d8aaa1SSean Wilcox /*
251613d8aaa1SSean Wilcox * This should never happen because the caller should fall through
251713d8aaa1SSean Wilcox * another path of just setting the ids to defaults, instead of
251813d8aaa1SSean Wilcox * attempting to get the ids here.
251913d8aaa1SSean Wilcox */
2520870ad75aSSean Wilcox if (methpg == NULL && instpg == NULL)
2521870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2522870ad75aSSean Wilcox "No property groups to get ids from."));
252313d8aaa1SSean Wilcox
252413d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_USER,
252513d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0 || get_astring_val(instpg,
252613d8aaa1SSean Wilcox SCF_PROPERTY_USER, vbuf, vbuf_sz, prop,
2527870ad75aSSean Wilcox val) == 0))
2528870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2529870ad75aSSean Wilcox "Could not get \"%s\" property.", SCF_PROPERTY_USER));
25307c478bd9Sstevel@tonic-gate
2531870ad75aSSean Wilcox if ((r = get_uid(vbuf, ci, &ci->uid)) != 0) {
2532f48205beScasper ci->uid = (uid_t)-1;
2533870ad75aSSean Wilcox return (mc_error_create(merr, r,
2534870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\", "
2535870ad75aSSean Wilcox "error %d.", SCF_PROPERTY_USER, vbuf, r));
25367c478bd9Sstevel@tonic-gate }
25377c478bd9Sstevel@tonic-gate
253813d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop,
253913d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_GROUP, vbuf,
254013d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0)) {
254113d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) {
254213d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default");
254313d8aaa1SSean Wilcox } else {
2544870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2545870ad75aSSean Wilcox "Could not get \"%s\" property.",
2546870ad75aSSean Wilcox SCF_PROPERTY_GROUP));
254713d8aaa1SSean Wilcox }
25487c478bd9Sstevel@tonic-gate }
25497c478bd9Sstevel@tonic-gate
25507c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) {
25517c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf);
2552f48205beScasper if (ci->gid == (gid_t)-1) {
2553870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2554870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".",
2555870ad75aSSean Wilcox SCF_PROPERTY_GROUP, vbuf));
25567c478bd9Sstevel@tonic-gate }
25577c478bd9Sstevel@tonic-gate } else {
25587c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) {
25597c478bd9Sstevel@tonic-gate case 0:
25607c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid;
25617c478bd9Sstevel@tonic-gate break;
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate case ENOENT:
2564f48205beScasper ci->gid = (gid_t)-1;
2565870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2566870ad75aSSean Wilcox "No passwd entry for uid \"%d\".", ci->uid));
25677c478bd9Sstevel@tonic-gate
25687c478bd9Sstevel@tonic-gate case ENOMEM:
2569870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM,
2570870ad75aSSean Wilcox "Out of memory."));
25717c478bd9Sstevel@tonic-gate
25727c478bd9Sstevel@tonic-gate case EIO:
25737c478bd9Sstevel@tonic-gate case EMFILE:
25747c478bd9Sstevel@tonic-gate case ENFILE:
2575870ad75aSSean Wilcox return (mc_error_create(merr, ENFILE,
2576870ad75aSSean Wilcox "getpwuid_r() failed, error %d.", r));
25777c478bd9Sstevel@tonic-gate
25787c478bd9Sstevel@tonic-gate default:
25797c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r);
25807c478bd9Sstevel@tonic-gate }
25817c478bd9Sstevel@tonic-gate }
25827c478bd9Sstevel@tonic-gate
258313d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz,
258413d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg,
258513d8aaa1SSean Wilcox SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, val) == 0)) {
258613d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) {
258713d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default");
258813d8aaa1SSean Wilcox } else {
2589870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2590870ad75aSSean Wilcox "Could not get supplemental groups (\"%s\") "
2591870ad75aSSean Wilcox "property.", SCF_PROPERTY_SUPP_GROUPS));
259213d8aaa1SSean Wilcox }
25937c478bd9Sstevel@tonic-gate }
25947c478bd9Sstevel@tonic-gate
25957c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) {
25967c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) {
25977c478bd9Sstevel@tonic-gate case 0:
25987c478bd9Sstevel@tonic-gate break;
25997c478bd9Sstevel@tonic-gate
26007c478bd9Sstevel@tonic-gate case EINVAL:
2601870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL,
2602870ad75aSSean Wilcox "Could not interpret supplemental groups (\"%s\") "
2603870ad75aSSean Wilcox "property value \"%s\".", SCF_PROPERTY_SUPP_GROUPS,
2604870ad75aSSean Wilcox vbuf));
26057c478bd9Sstevel@tonic-gate
26067c478bd9Sstevel@tonic-gate case E2BIG:
2607870ad75aSSean Wilcox return (mc_error_create(merr, E2BIG,
2608870ad75aSSean Wilcox "Too many supplemental groups values in \"%s\".",
2609870ad75aSSean Wilcox vbuf));
26107c478bd9Sstevel@tonic-gate
26117c478bd9Sstevel@tonic-gate default:
26127c478bd9Sstevel@tonic-gate bad_fail("get_groups", r);
26137c478bd9Sstevel@tonic-gate }
26147c478bd9Sstevel@tonic-gate } else {
26157c478bd9Sstevel@tonic-gate ci->ngroups = -1;
26167c478bd9Sstevel@tonic-gate }
26177c478bd9Sstevel@tonic-gate
261813d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz,
261913d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PRIVILEGES,
262013d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0)) {
262113d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) {
262213d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default");
262313d8aaa1SSean Wilcox } else {
2624870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2625870ad75aSSean Wilcox "Could not get \"%s\" property.",
2626870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES));
262713d8aaa1SSean Wilcox }
26287c478bd9Sstevel@tonic-gate }
26297c478bd9Sstevel@tonic-gate
26307c478bd9Sstevel@tonic-gate /*
26317c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as
26327c478bd9Sstevel@tonic-gate * we use this test elsewhere.
26337c478bd9Sstevel@tonic-gate */
26347c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) {
26357c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL);
26367c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) {
26377c478bd9Sstevel@tonic-gate if (errno != EINVAL) {
2638870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM,
2639870ad75aSSean Wilcox ALLOCFAIL));
26407c478bd9Sstevel@tonic-gate } else {
2641870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL,
2642870ad75aSSean Wilcox "Could not interpret \"%s\" "
2643870ad75aSSean Wilcox "property value \"%s\".",
2644870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES, vbuf));
26457c478bd9Sstevel@tonic-gate }
26467c478bd9Sstevel@tonic-gate }
26477c478bd9Sstevel@tonic-gate }
26487c478bd9Sstevel@tonic-gate
264913d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf,
265013d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0 || get_astring_val(instpg,
265113d8aaa1SSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, prop, val) == 0)) {
265213d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) {
265313d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default");
265413d8aaa1SSean Wilcox } else {
2655870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT,
2656870ad75aSSean Wilcox "Could not get \"%s\" property.",
2657870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES));
265813d8aaa1SSean Wilcox }
26597c478bd9Sstevel@tonic-gate }
26607c478bd9Sstevel@tonic-gate
26617c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0)
26627c478bd9Sstevel@tonic-gate /*
26637c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see
26647c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current
26657c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone.
26667c478bd9Sstevel@tonic-gate */
26677c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone");
26687c478bd9Sstevel@tonic-gate
26697c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL);
26707c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) {
2671870ad75aSSean Wilcox if (errno != EINVAL) {
2672870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, ALLOCFAIL));
2673870ad75aSSean Wilcox } else {
2674870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL,
2675870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".",
2676870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf));
26777c478bd9Sstevel@tonic-gate }
26787c478bd9Sstevel@tonic-gate }
26797c478bd9Sstevel@tonic-gate
2680870ad75aSSean Wilcox return (merr);
26817c478bd9Sstevel@tonic-gate }
26827c478bd9Sstevel@tonic-gate
26837c478bd9Sstevel@tonic-gate static int
get_environment(scf_handle_t * h,scf_propertygroup_t * pg,struct method_context * mcp,scf_property_t * prop,scf_value_t * val)26847c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg,
26857c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val)
26867c478bd9Sstevel@tonic-gate {
26877c478bd9Sstevel@tonic-gate scf_iter_t *iter;
26887c478bd9Sstevel@tonic-gate scf_type_t type;
26897c478bd9Sstevel@tonic-gate size_t i = 0;
26907c478bd9Sstevel@tonic-gate int ret;
26917c478bd9Sstevel@tonic-gate
26927c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) {
26937c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND)
26947c478bd9Sstevel@tonic-gate return (ENOENT);
26957c478bd9Sstevel@tonic-gate return (scf_error());
26967c478bd9Sstevel@tonic-gate }
26977c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0)
26987c478bd9Sstevel@tonic-gate return (scf_error());
26997c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING)
27007c478bd9Sstevel@tonic-gate return (EINVAL);
27017c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL)
27027c478bd9Sstevel@tonic-gate return (scf_error());
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) {
27057c478bd9Sstevel@tonic-gate ret = scf_error();
27067c478bd9Sstevel@tonic-gate scf_iter_destroy(iter);
27077c478bd9Sstevel@tonic-gate return (ret);
27087c478bd9Sstevel@tonic-gate }
27097c478bd9Sstevel@tonic-gate
27107c478bd9Sstevel@tonic-gate mcp->env_sz = 10;
27117c478bd9Sstevel@tonic-gate
27127c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) {
27137c478bd9Sstevel@tonic-gate ret = ENOMEM;
27147c478bd9Sstevel@tonic-gate goto out;
27157c478bd9Sstevel@tonic-gate }
27167c478bd9Sstevel@tonic-gate
27177c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) {
27187c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz);
27197c478bd9Sstevel@tonic-gate if (ret == -1) {
27207c478bd9Sstevel@tonic-gate ret = scf_error();
27217c478bd9Sstevel@tonic-gate goto out;
27227c478bd9Sstevel@tonic-gate }
27237c478bd9Sstevel@tonic-gate
27247c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) {
27257c478bd9Sstevel@tonic-gate ret = ENOMEM;
27267c478bd9Sstevel@tonic-gate goto out;
27277c478bd9Sstevel@tonic-gate }
27287c478bd9Sstevel@tonic-gate
27297c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) {
27307c478bd9Sstevel@tonic-gate char **env;
27317c478bd9Sstevel@tonic-gate mcp->env_sz *= 2;
27327c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz);
27337c478bd9Sstevel@tonic-gate if (env == NULL) {
27347c478bd9Sstevel@tonic-gate ret = ENOMEM;
27357c478bd9Sstevel@tonic-gate goto out;
27367c478bd9Sstevel@tonic-gate }
27377c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env,
27387c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2));
27397c478bd9Sstevel@tonic-gate free(mcp->env);
27407c478bd9Sstevel@tonic-gate mcp->env = env;
27417c478bd9Sstevel@tonic-gate }
27427c478bd9Sstevel@tonic-gate }
27437c478bd9Sstevel@tonic-gate
27447c478bd9Sstevel@tonic-gate if (ret == -1)
27457c478bd9Sstevel@tonic-gate ret = scf_error();
27467c478bd9Sstevel@tonic-gate
27477c478bd9Sstevel@tonic-gate out:
27487c478bd9Sstevel@tonic-gate scf_iter_destroy(iter);
27497c478bd9Sstevel@tonic-gate return (ret);
27507c478bd9Sstevel@tonic-gate }
27517c478bd9Sstevel@tonic-gate
27527c478bd9Sstevel@tonic-gate /*
27537c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill
2754870ad75aSSean Wilcox * a method_context structure, return it in *mcpp, and return NULL.
27557c478bd9Sstevel@tonic-gate *
275613d8aaa1SSean Wilcox * If no method_context is defined, original init context is provided, where
275713d8aaa1SSean Wilcox * the working directory is '/', and uid/gid are 0/0. But if a method_context
2758*bbf21555SRichard Lowe * is defined at any level the smf_method(7) method_context defaults are used.
275913d8aaa1SSean Wilcox *
2760870ad75aSSean Wilcox * Return an error message structure containing the error message
2761870ad75aSSean Wilcox * with context, and the error so the caller can make a decision
2762870ad75aSSean Wilcox * on what to do next.
2763870ad75aSSean Wilcox *
2764870ad75aSSean Wilcox * Error Types :
2765870ad75aSSean Wilcox * E2BIG Too many values or entry is too big
2766870ad75aSSean Wilcox * EINVAL Invalid value
2767870ad75aSSean Wilcox * EIO an I/O error has occured
2768870ad75aSSean Wilcox * ENOENT no entry for value
2769870ad75aSSean Wilcox * ENOMEM out of memory
2770870ad75aSSean Wilcox * ENOTSUP Version mismatch
2771870ad75aSSean Wilcox * ERANGE value is out of range
2772870ad75aSSean Wilcox * EMFILE/ENFILE out of file descriptors
2773870ad75aSSean Wilcox *
2774870ad75aSSean Wilcox * SCF_ERROR_BACKEND_ACCESS
2775870ad75aSSean Wilcox * SCF_ERROR_CONNECTION_BROKEN
2776870ad75aSSean Wilcox * SCF_ERROR_DELETED
2777870ad75aSSean Wilcox * SCF_ERROR_CONSTRAINT_VIOLATED
2778870ad75aSSean Wilcox * SCF_ERROR_HANDLE_DESTROYED
2779870ad75aSSean Wilcox * SCF_ERROR_INTERNAL
2780870ad75aSSean Wilcox * SCF_ERROR_INVALID_ARGUMENT
2781870ad75aSSean Wilcox * SCF_ERROR_NO_MEMORY
2782870ad75aSSean Wilcox * SCF_ERROR_NO_RESOURCES
2783870ad75aSSean Wilcox * SCF_ERROR_NOT_BOUND
2784870ad75aSSean Wilcox * SCF_ERROR_NOT_FOUND
2785870ad75aSSean Wilcox * SCF_ERROR_NOT_SET
2786870ad75aSSean Wilcox * SCF_ERROR_TYPE_MISMATCH
2787870ad75aSSean Wilcox *
27887c478bd9Sstevel@tonic-gate */
2789870ad75aSSean Wilcox mc_error_t *
restarter_get_method_context(uint_t version,scf_instance_t * inst,scf_snapshot_t * snap,const char * mname,const char * cmdline,struct method_context ** mcpp)27907c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst,
27917c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline,
27927c478bd9Sstevel@tonic-gate struct method_context **mcpp)
27937c478bd9Sstevel@tonic-gate {
27947c478bd9Sstevel@tonic-gate scf_handle_t *h;
27957c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL;
27967c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL;
27977c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL;
27987c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL;
27997c478bd9Sstevel@tonic-gate scf_value_t *val = NULL;
28007c478bd9Sstevel@tonic-gate scf_type_t ty;
28017c478bd9Sstevel@tonic-gate uint8_t use_profile;
2802870ad75aSSean Wilcox int ret = 0;
280313d8aaa1SSean Wilcox int mc_used = 0;
2804870ad75aSSean Wilcox mc_error_t *err = NULL;
28057c478bd9Sstevel@tonic-gate struct method_context *cip;
28067c478bd9Sstevel@tonic-gate
2807870ad75aSSean Wilcox if ((err = malloc(sizeof (mc_error_t))) == NULL)
2808870ad75aSSean Wilcox return (mc_error_create(NULL, ENOMEM, NULL));
2809870ad75aSSean Wilcox
2810870ad75aSSean Wilcox /* Set the type to zero to track if an error occured. */
2811870ad75aSSean Wilcox err->type = 0;
2812870ad75aSSean Wilcox
28137c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION)
2814870ad75aSSean Wilcox return (mc_error_create(err, ENOTSUP,
2815870ad75aSSean Wilcox "Invalid client version %d. (Expected %d)",
2816870ad75aSSean Wilcox version, RESTARTER_METHOD_CONTEXT_VERSION));
28177c478bd9Sstevel@tonic-gate
28187c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */
28197c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst);
28207c478bd9Sstevel@tonic-gate if (h == NULL)
2821870ad75aSSean Wilcox return (mc_error_create(err, scf_error(),
2822870ad75aSSean Wilcox scf_strerror(scf_error())));
28237c478bd9Sstevel@tonic-gate
28247c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip));
28257c478bd9Sstevel@tonic-gate if (cip == NULL)
2826870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL));
28277c478bd9Sstevel@tonic-gate
28287c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip));
2829f48205beScasper cip->uid = (uid_t)-1;
2830f48205beScasper cip->euid = (uid_t)-1;
2831f48205beScasper cip->gid = (gid_t)-1;
2832f48205beScasper cip->egid = (gid_t)-1;
28337c478bd9Sstevel@tonic-gate
28347c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
28357c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0);
28367c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz);
28377c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) {
28387c478bd9Sstevel@tonic-gate free(cip);
2839870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL));
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate
28427c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL ||
28437c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL ||
28447c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL ||
28457c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) {
2846870ad75aSSean Wilcox err = mc_error_create(err, scf_error(),
2847d2a70789SRichard Lowe "Failed to create repository object: %s",
2848870ad75aSSean Wilcox scf_strerror(scf_error()));
28497c478bd9Sstevel@tonic-gate goto out;
28507c478bd9Sstevel@tonic-gate }
28517c478bd9Sstevel@tonic-gate
28527c478bd9Sstevel@tonic-gate /*
28537c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data,
28547c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg),
28557c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named
28567c478bd9Sstevel@tonic-gate * instpg below).
28577c478bd9Sstevel@tonic-gate */
28587c478bd9Sstevel@tonic-gate
28597c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) !=
28607c478bd9Sstevel@tonic-gate SCF_SUCCESS) {
2861870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), "Unable to get the "
2862870ad75aSSean Wilcox "\"%s\" method, %s", mname, scf_strerror(scf_error()));
28637c478bd9Sstevel@tonic-gate goto out;
28647c478bd9Sstevel@tonic-gate }
28657c478bd9Sstevel@tonic-gate
28667c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT,
28677c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) {
28687c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) {
2869870ad75aSSean Wilcox err = mc_error_create(err, scf_error(),
2870870ad75aSSean Wilcox "Unable to retrieve the \"%s\" property group, %s",
2871870ad75aSSean Wilcox SCF_PG_METHOD_CONTEXT, scf_strerror(scf_error()));
28727c478bd9Sstevel@tonic-gate goto out;
28737c478bd9Sstevel@tonic-gate }
28747c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg);
28757c478bd9Sstevel@tonic-gate instpg = NULL;
287613d8aaa1SSean Wilcox } else {
287713d8aaa1SSean Wilcox mc_used++;
28787c478bd9Sstevel@tonic-gate }
28797c478bd9Sstevel@tonic-gate
28807c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val);
28817c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) {
28827c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val);
28837c478bd9Sstevel@tonic-gate }
28847c478bd9Sstevel@tonic-gate
28857c478bd9Sstevel@tonic-gate switch (ret) {
28867c478bd9Sstevel@tonic-gate case 0:
288713d8aaa1SSean Wilcox mc_used++;
288813d8aaa1SSean Wilcox break;
28897c478bd9Sstevel@tonic-gate case ENOENT:
28907c478bd9Sstevel@tonic-gate break;
28917c478bd9Sstevel@tonic-gate case ENOMEM:
2892870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory.");
28937c478bd9Sstevel@tonic-gate goto out;
28947c478bd9Sstevel@tonic-gate case EINVAL:
2895870ad75aSSean Wilcox err = mc_error_create(err, ret, "Invalid method environment.");
28967c478bd9Sstevel@tonic-gate goto out;
28977c478bd9Sstevel@tonic-gate default:
2898870ad75aSSean Wilcox err = mc_error_create(err, ret,
2899d2a70789SRichard Lowe "Get method environment failed: %s", scf_strerror(ret));
29007c478bd9Sstevel@tonic-gate goto out;
29017c478bd9Sstevel@tonic-gate }
29027c478bd9Sstevel@tonic-gate
29037c478bd9Sstevel@tonic-gate pg = methpg;
29047c478bd9Sstevel@tonic-gate
29057c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop);
29067c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) {
290713d8aaa1SSean Wilcox pg = NULL;
290813d8aaa1SSean Wilcox ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE,
290913d8aaa1SSean Wilcox prop);
29107c478bd9Sstevel@tonic-gate }
29117c478bd9Sstevel@tonic-gate
29127c478bd9Sstevel@tonic-gate if (ret) {
29137c478bd9Sstevel@tonic-gate switch (scf_error()) {
29147c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
291513d8aaa1SSean Wilcox /* No profile context: use default credentials */
29167c478bd9Sstevel@tonic-gate cip->uid = 0;
29177c478bd9Sstevel@tonic-gate cip->gid = 0;
291813d8aaa1SSean Wilcox break;
29197c478bd9Sstevel@tonic-gate
29207c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
2921870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_CONNECTION_BROKEN,
2922870ad75aSSean Wilcox RCBROKEN);
29237c478bd9Sstevel@tonic-gate goto out;
29247c478bd9Sstevel@tonic-gate
29257c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
2926870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_NOT_FOUND,
2927870ad75aSSean Wilcox "Could not find property group \"%s\"",
2928870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
29297c478bd9Sstevel@tonic-gate goto out;
29307c478bd9Sstevel@tonic-gate
29317c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
29327c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
29337c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
29347c478bd9Sstevel@tonic-gate default:
29357c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error());
29367c478bd9Sstevel@tonic-gate }
293713d8aaa1SSean Wilcox } else {
293813d8aaa1SSean Wilcox if (scf_property_type(prop, &ty) != SCF_SUCCESS) {
2939870ad75aSSean Wilcox ret = scf_error();
2940870ad75aSSean Wilcox switch (ret) {
294113d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
2942870ad75aSSean Wilcox err = mc_error_create(err,
2943870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN);
294413d8aaa1SSean Wilcox break;
29457c478bd9Sstevel@tonic-gate
294613d8aaa1SSean Wilcox case SCF_ERROR_DELETED:
2947870ad75aSSean Wilcox err = mc_error_create(err,
2948870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND,
2949870ad75aSSean Wilcox "Could not find property group \"%s\"",
2950870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
295113d8aaa1SSean Wilcox break;
29527c478bd9Sstevel@tonic-gate
295313d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET:
295413d8aaa1SSean Wilcox default:
2955870ad75aSSean Wilcox bad_fail("scf_property_type", ret);
295613d8aaa1SSean Wilcox }
29577c478bd9Sstevel@tonic-gate
295813d8aaa1SSean Wilcox goto out;
29597c478bd9Sstevel@tonic-gate }
29607c478bd9Sstevel@tonic-gate
296113d8aaa1SSean Wilcox if (ty != SCF_TYPE_BOOLEAN) {
2962870ad75aSSean Wilcox err = mc_error_create(err,
2963870ad75aSSean Wilcox SCF_ERROR_TYPE_MISMATCH,
2964870ad75aSSean Wilcox "\"%s\" property is not boolean in property group "
2965870ad75aSSean Wilcox "\"%s\".", SCF_PROPERTY_USE_PROFILE,
2966870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
296713d8aaa1SSean Wilcox goto out;
296813d8aaa1SSean Wilcox }
29697c478bd9Sstevel@tonic-gate
297013d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2971870ad75aSSean Wilcox ret = scf_error();
2972870ad75aSSean Wilcox switch (ret) {
297313d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
2974870ad75aSSean Wilcox err = mc_error_create(err,
2975870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN);
297613d8aaa1SSean Wilcox break;
29777c478bd9Sstevel@tonic-gate
297813d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED:
2979870ad75aSSean Wilcox err = mc_error_create(err,
2980870ad75aSSean Wilcox SCF_ERROR_CONSTRAINT_VIOLATED,
2981870ad75aSSean Wilcox "\"%s\" property has multiple values.",
2982870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE);
298313d8aaa1SSean Wilcox break;
29847c478bd9Sstevel@tonic-gate
298513d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
2986870ad75aSSean Wilcox err = mc_error_create(err,
2987870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND,
2988870ad75aSSean Wilcox "\"%s\" property has no values.",
2989870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE);
299013d8aaa1SSean Wilcox break;
299113d8aaa1SSean Wilcox default:
2992870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret);
299313d8aaa1SSean Wilcox }
29947c478bd9Sstevel@tonic-gate
299513d8aaa1SSean Wilcox goto out;
29967c478bd9Sstevel@tonic-gate }
29977c478bd9Sstevel@tonic-gate
299813d8aaa1SSean Wilcox mc_used++;
299913d8aaa1SSean Wilcox ret = scf_value_get_boolean(val, &use_profile);
300013d8aaa1SSean Wilcox assert(ret == SCF_SUCCESS);
30017c478bd9Sstevel@tonic-gate
300213d8aaa1SSean Wilcox /* get ids & privileges */
300313d8aaa1SSean Wilcox if (use_profile)
3004870ad75aSSean Wilcox err = get_profile(pg, instpg, prop, val, cmdline,
3005870ad75aSSean Wilcox cip, err);
300613d8aaa1SSean Wilcox else
3007870ad75aSSean Wilcox err = get_ids(pg, instpg, prop, val, cip, err);
30087c478bd9Sstevel@tonic-gate
3009870ad75aSSean Wilcox if (err->type != 0)
301013d8aaa1SSean Wilcox goto out;
301113d8aaa1SSean Wilcox }
30127c478bd9Sstevel@tonic-gate
30137c478bd9Sstevel@tonic-gate /* get working directory */
301413d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg,
301513d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS) ||
301613d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg,
301713d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS)) {
301813d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3019870ad75aSSean Wilcox ret = scf_error();
3020870ad75aSSean Wilcox switch (ret) {
302113d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3022870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN);
302313d8aaa1SSean Wilcox break;
302413d8aaa1SSean Wilcox
302513d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED:
3026870ad75aSSean Wilcox err = mc_error_create(err, ret,
3027870ad75aSSean Wilcox "\"%s\" property has multiple values.",
3028870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY);
302913d8aaa1SSean Wilcox break;
303013d8aaa1SSean Wilcox
303113d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
3032870ad75aSSean Wilcox err = mc_error_create(err, ret,
3033870ad75aSSean Wilcox "\"%s\" property has no values.",
3034870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY);
303513d8aaa1SSean Wilcox break;
303613d8aaa1SSean Wilcox
303713d8aaa1SSean Wilcox default:
3038870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret);
303913d8aaa1SSean Wilcox }
304013d8aaa1SSean Wilcox
304113d8aaa1SSean Wilcox goto out;
304213d8aaa1SSean Wilcox }
304313d8aaa1SSean Wilcox
304413d8aaa1SSean Wilcox mc_used++;
304513d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, cip->vbuf_sz);
304613d8aaa1SSean Wilcox assert(ret != -1);
304713d8aaa1SSean Wilcox } else {
3048870ad75aSSean Wilcox ret = scf_error();
3049870ad75aSSean Wilcox switch (ret) {
305013d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
305113d8aaa1SSean Wilcox /* okay if missing. */
305213d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default");
305313d8aaa1SSean Wilcox break;
305413d8aaa1SSean Wilcox
305513d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3056870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN);
305713d8aaa1SSean Wilcox goto out;
305813d8aaa1SSean Wilcox
305913d8aaa1SSean Wilcox case SCF_ERROR_DELETED:
3060870ad75aSSean Wilcox err = mc_error_create(err, ret,
3061870ad75aSSean Wilcox "Property group could not be found");
306213d8aaa1SSean Wilcox goto out;
306313d8aaa1SSean Wilcox
306413d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH:
306513d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT:
306613d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET:
306713d8aaa1SSean Wilcox default:
3068870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret);
306913d8aaa1SSean Wilcox }
30707c478bd9Sstevel@tonic-gate }
30717c478bd9Sstevel@tonic-gate
30727c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 ||
30737c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) {
30747c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) {
30757c478bd9Sstevel@tonic-gate case 0:
30767c478bd9Sstevel@tonic-gate break;
30777c478bd9Sstevel@tonic-gate
30787c478bd9Sstevel@tonic-gate case ENOMEM:
3079870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory.");
30807c478bd9Sstevel@tonic-gate goto out;
30817c478bd9Sstevel@tonic-gate
30827c478bd9Sstevel@tonic-gate case ENOENT:
30837c478bd9Sstevel@tonic-gate case EIO:
30847c478bd9Sstevel@tonic-gate case EMFILE:
30857c478bd9Sstevel@tonic-gate case ENFILE:
3086870ad75aSSean Wilcox err = mc_error_create(err, ret,
3087870ad75aSSean Wilcox "Could not get passwd entry.");
30887c478bd9Sstevel@tonic-gate goto out;
30897c478bd9Sstevel@tonic-gate
30907c478bd9Sstevel@tonic-gate default:
30917c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret);
30927c478bd9Sstevel@tonic-gate }
30937c478bd9Sstevel@tonic-gate
30947c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir);
30957c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) {
3096870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL);
30977c478bd9Sstevel@tonic-gate goto out;
30987c478bd9Sstevel@tonic-gate }
30997c478bd9Sstevel@tonic-gate } else {
31007c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf);
31017c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) {
3102870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL);
31037c478bd9Sstevel@tonic-gate goto out;
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate }
31067c478bd9Sstevel@tonic-gate
3107d2a70789SRichard Lowe /* get security flags */
3108d2a70789SRichard Lowe if ((methpg != NULL && scf_pg_get_property(methpg,
3109d2a70789SRichard Lowe SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS) ||
3110d2a70789SRichard Lowe (instpg != NULL && scf_pg_get_property(instpg,
3111d2a70789SRichard Lowe SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS)) {
3112d2a70789SRichard Lowe if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3113d2a70789SRichard Lowe ret = scf_error();
3114d2a70789SRichard Lowe switch (ret) {
3115d2a70789SRichard Lowe case SCF_ERROR_CONNECTION_BROKEN:
3116d2a70789SRichard Lowe err = mc_error_create(err, ret, RCBROKEN);
3117d2a70789SRichard Lowe break;
3118d2a70789SRichard Lowe
3119d2a70789SRichard Lowe case SCF_ERROR_CONSTRAINT_VIOLATED:
3120d2a70789SRichard Lowe err = mc_error_create(err, ret,
3121d2a70789SRichard Lowe "\"%s\" property has multiple values.",
3122d2a70789SRichard Lowe SCF_PROPERTY_SECFLAGS);
3123d2a70789SRichard Lowe break;
3124d2a70789SRichard Lowe
3125d2a70789SRichard Lowe case SCF_ERROR_NOT_FOUND:
3126d2a70789SRichard Lowe err = mc_error_create(err, ret,
3127d2a70789SRichard Lowe "\"%s\" property has no values.",
3128d2a70789SRichard Lowe SCF_PROPERTY_SECFLAGS);
3129d2a70789SRichard Lowe break;
3130d2a70789SRichard Lowe
3131d2a70789SRichard Lowe default:
3132d2a70789SRichard Lowe bad_fail("scf_property_get_value", ret);
3133d2a70789SRichard Lowe }
3134d2a70789SRichard Lowe
3135d2a70789SRichard Lowe (void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
3136d2a70789SRichard Lowe } else {
3137d2a70789SRichard Lowe ret = scf_value_get_astring(val, cip->vbuf,
3138d2a70789SRichard Lowe cip->vbuf_sz);
3139d2a70789SRichard Lowe assert(ret != -1);
3140d2a70789SRichard Lowe }
3141d2a70789SRichard Lowe mc_used++;
3142d2a70789SRichard Lowe } else {
3143d2a70789SRichard Lowe ret = scf_error();
3144d2a70789SRichard Lowe switch (ret) {
3145d2a70789SRichard Lowe case SCF_ERROR_NOT_FOUND:
3146d2a70789SRichard Lowe /* okay if missing. */
3147d2a70789SRichard Lowe (void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
3148d2a70789SRichard Lowe break;
3149d2a70789SRichard Lowe
3150d2a70789SRichard Lowe case SCF_ERROR_CONNECTION_BROKEN:
3151d2a70789SRichard Lowe err = mc_error_create(err, ret, RCBROKEN);
3152d2a70789SRichard Lowe goto out;
3153d2a70789SRichard Lowe
3154d2a70789SRichard Lowe case SCF_ERROR_DELETED:
3155d2a70789SRichard Lowe err = mc_error_create(err, ret,
3156d2a70789SRichard Lowe "Property group could not be found");
3157d2a70789SRichard Lowe goto out;
3158d2a70789SRichard Lowe
3159d2a70789SRichard Lowe case SCF_ERROR_HANDLE_MISMATCH:
3160d2a70789SRichard Lowe case SCF_ERROR_INVALID_ARGUMENT:
3161d2a70789SRichard Lowe case SCF_ERROR_NOT_SET:
3162d2a70789SRichard Lowe default:
3163d2a70789SRichard Lowe bad_fail("scf_pg_get_property", ret);
3164d2a70789SRichard Lowe }
3165d2a70789SRichard Lowe }
3166d2a70789SRichard Lowe
3167d2a70789SRichard Lowe
3168d2a70789SRichard Lowe if (scf_default_secflags(h, &cip->def_secflags) != 0) {
3169d2a70789SRichard Lowe err = mc_error_create(err, EINVAL, "couldn't fetch "
3170d2a70789SRichard Lowe "default security-flags");
3171d2a70789SRichard Lowe goto out;
3172d2a70789SRichard Lowe }
3173d2a70789SRichard Lowe
3174d2a70789SRichard Lowe if (strcmp(cip->vbuf, ":default") != 0) {
3175d2a70789SRichard Lowe if (secflags_parse(NULL, cip->vbuf,
3176d2a70789SRichard Lowe &cip->secflag_delta) != 0) {
3177d2a70789SRichard Lowe err = mc_error_create(err, EINVAL, "couldn't parse "
3178d2a70789SRichard Lowe "security flags: %s", cip->vbuf);
3179d2a70789SRichard Lowe goto out;
3180d2a70789SRichard Lowe }
3181d2a70789SRichard Lowe }
3182d2a70789SRichard Lowe
31837c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */
318413d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg,
318513d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) ||
318613d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg,
318713d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) {
318813d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3189870ad75aSSean Wilcox ret = scf_error();
3190870ad75aSSean Wilcox switch (ret) {
319113d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3192870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN);
319313d8aaa1SSean Wilcox break;
31947c478bd9Sstevel@tonic-gate
319513d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED:
3196870ad75aSSean Wilcox err = mc_error_create(err, ret,
3197870ad75aSSean Wilcox "\"%s\" property has multiple values.",
3198870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN);
319913d8aaa1SSean Wilcox break;
320013d8aaa1SSean Wilcox
320113d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
3202870ad75aSSean Wilcox err = mc_error_create(err, ret,
3203870ad75aSSean Wilcox "\"%s\" property has no values.",
3204870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN);
320513d8aaa1SSean Wilcox break;
320613d8aaa1SSean Wilcox
320713d8aaa1SSean Wilcox default:
3208870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret);
320913d8aaa1SSean Wilcox }
321013d8aaa1SSean Wilcox
321113d8aaa1SSean Wilcox } else {
321213d8aaa1SSean Wilcox
321313d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf,
321413d8aaa1SSean Wilcox cip->vbuf_sz);
321513d8aaa1SSean Wilcox assert(ret != -1);
321613d8aaa1SSean Wilcox
321713d8aaa1SSean Wilcox cip->corefile_pattern = strdup(cip->vbuf);
321813d8aaa1SSean Wilcox if (cip->corefile_pattern == NULL) {
3219870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL);
322013d8aaa1SSean Wilcox goto out;
322113d8aaa1SSean Wilcox }
32227c478bd9Sstevel@tonic-gate }
322313d8aaa1SSean Wilcox
322413d8aaa1SSean Wilcox mc_used++;
32257c478bd9Sstevel@tonic-gate } else {
3226870ad75aSSean Wilcox ret = scf_error();
3227870ad75aSSean Wilcox switch (ret) {
32287c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND:
32297c478bd9Sstevel@tonic-gate /* okay if missing. */
32307c478bd9Sstevel@tonic-gate break;
32317c478bd9Sstevel@tonic-gate
32327c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN:
3233870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN);
32347c478bd9Sstevel@tonic-gate goto out;
32357c478bd9Sstevel@tonic-gate
32367c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED:
3237870ad75aSSean Wilcox err = mc_error_create(err, ret,
3238870ad75aSSean Wilcox "Property group could not be found");
32397c478bd9Sstevel@tonic-gate goto out;
32407c478bd9Sstevel@tonic-gate
32417c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH:
32427c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT:
32437c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET:
32447c478bd9Sstevel@tonic-gate default:
3245870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret);
32467c478bd9Sstevel@tonic-gate }
32477c478bd9Sstevel@tonic-gate }
32487c478bd9Sstevel@tonic-gate
32497c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) {
32507c478bd9Sstevel@tonic-gate /* get project */
325113d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg,
325213d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS) ||
325313d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg,
325413d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS)) {
325513d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3256870ad75aSSean Wilcox ret = scf_error();
3257870ad75aSSean Wilcox switch (ret) {
325813d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3259870ad75aSSean Wilcox err = mc_error_create(err, ret,
3260870ad75aSSean Wilcox RCBROKEN);
326113d8aaa1SSean Wilcox break;
326213d8aaa1SSean Wilcox
326313d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED:
3264870ad75aSSean Wilcox err = mc_error_create(err, ret,
3265870ad75aSSean Wilcox "\"%s\" property has multiple "
3266870ad75aSSean Wilcox "values.", SCF_PROPERTY_PROJECT);
326713d8aaa1SSean Wilcox break;
326813d8aaa1SSean Wilcox
326913d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
3270870ad75aSSean Wilcox err = mc_error_create(err, ret,
3271870ad75aSSean Wilcox "\"%s\" property has no values.",
3272870ad75aSSean Wilcox SCF_PROPERTY_PROJECT);
327313d8aaa1SSean Wilcox break;
327413d8aaa1SSean Wilcox
327513d8aaa1SSean Wilcox default:
3276870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret);
327713d8aaa1SSean Wilcox }
327813d8aaa1SSean Wilcox
327913d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default");
328013d8aaa1SSean Wilcox } else {
328113d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf,
328213d8aaa1SSean Wilcox cip->vbuf_sz);
328313d8aaa1SSean Wilcox assert(ret != -1);
328413d8aaa1SSean Wilcox }
328513d8aaa1SSean Wilcox
328613d8aaa1SSean Wilcox mc_used++;
328713d8aaa1SSean Wilcox } else {
328813d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default");
32897c478bd9Sstevel@tonic-gate }
32907c478bd9Sstevel@tonic-gate
32917c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) {
32927c478bd9Sstevel@tonic-gate case 0:
32937c478bd9Sstevel@tonic-gate break;
32947c478bd9Sstevel@tonic-gate
32957c478bd9Sstevel@tonic-gate case ENOMEM:
3296870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory.");
32977c478bd9Sstevel@tonic-gate goto out;
32987c478bd9Sstevel@tonic-gate
32997c478bd9Sstevel@tonic-gate case ENOENT:
3300870ad75aSSean Wilcox err = mc_error_create(err, ret,
3301870ad75aSSean Wilcox "Missing passwd or project entry for \"%s\".",
3302870ad75aSSean Wilcox cip->vbuf);
33037c478bd9Sstevel@tonic-gate goto out;
33047c478bd9Sstevel@tonic-gate
33057c478bd9Sstevel@tonic-gate case EIO:
3306870ad75aSSean Wilcox err = mc_error_create(err, ret, "I/O error.");
33077c478bd9Sstevel@tonic-gate goto out;
33087c478bd9Sstevel@tonic-gate
33097c478bd9Sstevel@tonic-gate case EMFILE:
33107c478bd9Sstevel@tonic-gate case ENFILE:
3311870ad75aSSean Wilcox err = mc_error_create(err, ret,
3312870ad75aSSean Wilcox "Out of file descriptors.");
33137c478bd9Sstevel@tonic-gate goto out;
33147c478bd9Sstevel@tonic-gate
33157c478bd9Sstevel@tonic-gate case -1:
3316870ad75aSSean Wilcox err = mc_error_create(err, ret,
3317870ad75aSSean Wilcox "Name service switch is misconfigured.");
33187c478bd9Sstevel@tonic-gate goto out;
33197c478bd9Sstevel@tonic-gate
33207c478bd9Sstevel@tonic-gate case ERANGE:
3321870ad75aSSean Wilcox case E2BIG:
3322870ad75aSSean Wilcox err = mc_error_create(err, ret,
3323870ad75aSSean Wilcox "Project ID \"%s\" too big.", cip->vbuf);
33247c478bd9Sstevel@tonic-gate goto out;
33257c478bd9Sstevel@tonic-gate
33267c478bd9Sstevel@tonic-gate case EINVAL:
3327870ad75aSSean Wilcox err = mc_error_create(err, ret,
3328870ad75aSSean Wilcox "Project ID \"%s\" is invalid.", cip->vbuf);
33297c478bd9Sstevel@tonic-gate goto out;
33307c478bd9Sstevel@tonic-gate
33317c478bd9Sstevel@tonic-gate default:
33327c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret);
33337c478bd9Sstevel@tonic-gate }
33347c478bd9Sstevel@tonic-gate
33357c478bd9Sstevel@tonic-gate /* get resource pool */
333613d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg,
333713d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS) ||
333813d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg,
333913d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS)) {
334013d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3341870ad75aSSean Wilcox ret = scf_error();
3342870ad75aSSean Wilcox switch (ret) {
334313d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3344870ad75aSSean Wilcox err = mc_error_create(err, ret,
3345870ad75aSSean Wilcox RCBROKEN);
334613d8aaa1SSean Wilcox break;
334713d8aaa1SSean Wilcox
334813d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED:
3349870ad75aSSean Wilcox err = mc_error_create(err, ret,
3350870ad75aSSean Wilcox "\"%s\" property has multiple "
3351870ad75aSSean Wilcox "values.",
3352870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL);
335313d8aaa1SSean Wilcox break;
335413d8aaa1SSean Wilcox
335513d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
3356870ad75aSSean Wilcox err = mc_error_create(err, ret,
3357870ad75aSSean Wilcox "\"%s\" property has no "
3358870ad75aSSean Wilcox "values.",
3359870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL);
336013d8aaa1SSean Wilcox break;
336113d8aaa1SSean Wilcox
336213d8aaa1SSean Wilcox default:
3363870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret);
336413d8aaa1SSean Wilcox }
336513d8aaa1SSean Wilcox
336613d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default");
336713d8aaa1SSean Wilcox } else {
336813d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf,
336913d8aaa1SSean Wilcox cip->vbuf_sz);
337013d8aaa1SSean Wilcox assert(ret != -1);
337113d8aaa1SSean Wilcox }
337213d8aaa1SSean Wilcox
337313d8aaa1SSean Wilcox mc_used++;
337413d8aaa1SSean Wilcox } else {
3375870ad75aSSean Wilcox ret = scf_error();
3376870ad75aSSean Wilcox switch (ret) {
337713d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND:
337813d8aaa1SSean Wilcox /* okay if missing. */
337913d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default");
338013d8aaa1SSean Wilcox break;
338113d8aaa1SSean Wilcox
338213d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN:
3383870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN);
338413d8aaa1SSean Wilcox goto out;
338513d8aaa1SSean Wilcox
338613d8aaa1SSean Wilcox case SCF_ERROR_DELETED:
3387870ad75aSSean Wilcox err = mc_error_create(err, ret,
3388870ad75aSSean Wilcox "property group could not be found.");
338913d8aaa1SSean Wilcox goto out;
339013d8aaa1SSean Wilcox
339113d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH:
339213d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT:
339313d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET:
339413d8aaa1SSean Wilcox default:
3395870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret);
339613d8aaa1SSean Wilcox }
33977c478bd9Sstevel@tonic-gate }
33987c478bd9Sstevel@tonic-gate
33997c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) {
34007c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf);
34017c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) {
3402870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL);
34037c478bd9Sstevel@tonic-gate goto out;
34047c478bd9Sstevel@tonic-gate }
34057c478bd9Sstevel@tonic-gate }
34067c478bd9Sstevel@tonic-gate }
34077c478bd9Sstevel@tonic-gate
340813d8aaa1SSean Wilcox /*
340913d8aaa1SSean Wilcox * A method_context was not used for any configurable
341013d8aaa1SSean Wilcox * elements or attributes, so reset and use the simple
341113d8aaa1SSean Wilcox * defaults that provide historic init behavior.
341213d8aaa1SSean Wilcox */
341313d8aaa1SSean Wilcox if (mc_used == 0) {
34143dd94f79SBryan Cantrill free(cip->pwbuf);
34153dd94f79SBryan Cantrill free(cip->vbuf);
34163dd94f79SBryan Cantrill free(cip->working_dir);
34173dd94f79SBryan Cantrill
341813d8aaa1SSean Wilcox (void) memset(cip, 0, sizeof (*cip));
341913d8aaa1SSean Wilcox cip->uid = 0;
342013d8aaa1SSean Wilcox cip->gid = 0;
342113d8aaa1SSean Wilcox cip->euid = (uid_t)-1;
342213d8aaa1SSean Wilcox cip->egid = (gid_t)-1;
3423d2a70789SRichard Lowe
3424d2a70789SRichard Lowe if (scf_default_secflags(h, &cip->def_secflags) != 0) {
3425d2a70789SRichard Lowe err = mc_error_create(err, EINVAL, "couldn't fetch "
3426d2a70789SRichard Lowe "default security-flags");
3427d2a70789SRichard Lowe goto out;
3428d2a70789SRichard Lowe }
342913d8aaa1SSean Wilcox }
343013d8aaa1SSean Wilcox
34317c478bd9Sstevel@tonic-gate *mcpp = cip;
34327c478bd9Sstevel@tonic-gate
34337c478bd9Sstevel@tonic-gate out:
34347c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val);
34357c478bd9Sstevel@tonic-gate scf_property_destroy(prop);
34367c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg);
34377c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg);
34387c478bd9Sstevel@tonic-gate
34393dd94f79SBryan Cantrill if (cip->pwbuf != NULL) {
34407c478bd9Sstevel@tonic-gate free(cip->pwbuf);
34413dd94f79SBryan Cantrill cip->pwbuf = NULL;
34423dd94f79SBryan Cantrill }
34433dd94f79SBryan Cantrill
34447c478bd9Sstevel@tonic-gate free(cip->vbuf);
34457c478bd9Sstevel@tonic-gate
3446870ad75aSSean Wilcox if (err->type != 0) {
34477c478bd9Sstevel@tonic-gate restarter_free_method_context(cip);
3448870ad75aSSean Wilcox } else {
3449870ad75aSSean Wilcox restarter_mc_error_destroy(err);
3450870ad75aSSean Wilcox err = NULL;
3451870ad75aSSean Wilcox }
34527c478bd9Sstevel@tonic-gate
3453870ad75aSSean Wilcox return (err);
34547c478bd9Sstevel@tonic-gate }
34557c478bd9Sstevel@tonic-gate
34567c478bd9Sstevel@tonic-gate /*
34577c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns
34587c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the
34597c478bd9Sstevel@tonic-gate * environment variables in cip->env.
34607c478bd9Sstevel@tonic-gate *
34617c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed,
34627c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are
34637c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case.
34647c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed
34657c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir)
34667c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r)
34677c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r)
34687c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid)
34697c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups)
34707c478bd9Sstevel@tonic-gate * project's project id is bad (setproject)
34717c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid)
34723ad28c1eSrm * poolname is invalid (pool_set_binding)
34737c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv,
34747c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid)
34757c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry
34767c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir)
34777c478bd9Sstevel@tonic-gate * uid has no passwd entry
34787c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding)
34797c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv)
34807c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir)
34817c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir)
34827c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid)
34837c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject)
34847c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir)
34857c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir)
34867c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir)
34877c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir)
34887c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject)
34897c478bd9Sstevel@tonic-gate * project is invalid (setproject)
34907c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject)
34917c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding)
34927c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path)
34937c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject)
34947c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding)
34957c478bd9Sstevel@tonic-gate */
34967c478bd9Sstevel@tonic-gate int
restarter_set_method_context(struct method_context * cip,const char ** fp)34977c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp)
34987c478bd9Sstevel@tonic-gate {
34997c478bd9Sstevel@tonic-gate pid_t mypid = -1;
35007c478bd9Sstevel@tonic-gate int r, ret;
35017c478bd9Sstevel@tonic-gate
35027c478bd9Sstevel@tonic-gate cip->pwbuf = NULL;
35037c478bd9Sstevel@tonic-gate *fp = NULL;
35047c478bd9Sstevel@tonic-gate
3505f48205beScasper if (cip->gid != (gid_t)-1) {
35067c478bd9Sstevel@tonic-gate if (setregid(cip->gid,
3507f48205beScasper cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) {
35087c478bd9Sstevel@tonic-gate *fp = "setregid";
35097c478bd9Sstevel@tonic-gate
35107c478bd9Sstevel@tonic-gate ret = errno;
35117c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM);
35127c478bd9Sstevel@tonic-gate goto out;
35137c478bd9Sstevel@tonic-gate }
35147c478bd9Sstevel@tonic-gate } else {
35157c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) {
35167c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) {
35177c478bd9Sstevel@tonic-gate case 0:
35187c478bd9Sstevel@tonic-gate break;
35197c478bd9Sstevel@tonic-gate
35207c478bd9Sstevel@tonic-gate case ENOMEM:
35217c478bd9Sstevel@tonic-gate case ENOENT:
35227c478bd9Sstevel@tonic-gate *fp = NULL;
35237c478bd9Sstevel@tonic-gate goto out;
35247c478bd9Sstevel@tonic-gate
35257c478bd9Sstevel@tonic-gate case EIO:
35267c478bd9Sstevel@tonic-gate case EMFILE:
35277c478bd9Sstevel@tonic-gate case ENFILE:
35287c478bd9Sstevel@tonic-gate *fp = "getpwuid_r";
35297c478bd9Sstevel@tonic-gate goto out;
35307c478bd9Sstevel@tonic-gate
35317c478bd9Sstevel@tonic-gate default:
35327c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret);
35337c478bd9Sstevel@tonic-gate }
35347c478bd9Sstevel@tonic-gate }
35357c478bd9Sstevel@tonic-gate
35367c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid,
3537f48205beScasper cip->egid != (gid_t)-1 ?
3538f48205beScasper cip->egid : cip->pwd.pw_gid) != 0) {
35397c478bd9Sstevel@tonic-gate *fp = "setregid";
35407c478bd9Sstevel@tonic-gate
35417c478bd9Sstevel@tonic-gate ret = errno;
35427c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM);
35437c478bd9Sstevel@tonic-gate goto out;
35447c478bd9Sstevel@tonic-gate }
35457c478bd9Sstevel@tonic-gate }
35467c478bd9Sstevel@tonic-gate
35477c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) {
35487c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) {
35497c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) {
35507c478bd9Sstevel@tonic-gate case 0:
35517c478bd9Sstevel@tonic-gate break;
35527c478bd9Sstevel@tonic-gate
35537c478bd9Sstevel@tonic-gate case ENOMEM:
35547c478bd9Sstevel@tonic-gate case ENOENT:
35557c478bd9Sstevel@tonic-gate *fp = NULL;
35567c478bd9Sstevel@tonic-gate goto out;
35577c478bd9Sstevel@tonic-gate
35587c478bd9Sstevel@tonic-gate case EIO:
35597c478bd9Sstevel@tonic-gate case EMFILE:
35607c478bd9Sstevel@tonic-gate case ENFILE:
35617c478bd9Sstevel@tonic-gate *fp = "getpwuid_r";
35627c478bd9Sstevel@tonic-gate goto out;
35637c478bd9Sstevel@tonic-gate
35647c478bd9Sstevel@tonic-gate default:
35657c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret);
35667c478bd9Sstevel@tonic-gate }
35677c478bd9Sstevel@tonic-gate }
35687c478bd9Sstevel@tonic-gate
35697c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */
35707c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) {
35717c478bd9Sstevel@tonic-gate *fp = "initgroups";
35727c478bd9Sstevel@tonic-gate ret = errno;
35737c478bd9Sstevel@tonic-gate assert(ret == EPERM);
35747c478bd9Sstevel@tonic-gate goto out;
35757c478bd9Sstevel@tonic-gate }
35767c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 &&
35777c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) {
35787c478bd9Sstevel@tonic-gate *fp = "setgroups";
35797c478bd9Sstevel@tonic-gate
35807c478bd9Sstevel@tonic-gate ret = errno;
35817c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM);
35827c478bd9Sstevel@tonic-gate goto out;
35837c478bd9Sstevel@tonic-gate }
35847c478bd9Sstevel@tonic-gate
35857c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) {
35867c478bd9Sstevel@tonic-gate mypid = getpid();
35877c478bd9Sstevel@tonic-gate
35887c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern,
35897c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) {
35907c478bd9Sstevel@tonic-gate *fp = "core_set_process_path";
35917c478bd9Sstevel@tonic-gate ret = -1;
35927c478bd9Sstevel@tonic-gate goto out;
35937c478bd9Sstevel@tonic-gate }
35947c478bd9Sstevel@tonic-gate }
35957c478bd9Sstevel@tonic-gate
3596d2a70789SRichard Lowe
3597d2a70789SRichard Lowe if (psecflags(P_PID, P_MYID, PSF_INHERIT,
3598d2a70789SRichard Lowe &cip->def_secflags.ss_default) != 0) {
3599d2a70789SRichard Lowe *fp = "psecflags (default inherit)";
3600d2a70789SRichard Lowe ret = errno;
3601d2a70789SRichard Lowe goto out;
3602d2a70789SRichard Lowe }
3603d2a70789SRichard Lowe
3604d2a70789SRichard Lowe if (psecflags(P_PID, P_MYID, PSF_LOWER,
3605d2a70789SRichard Lowe &cip->def_secflags.ss_lower) != 0) {
3606d2a70789SRichard Lowe *fp = "psecflags (default lower)";
3607d2a70789SRichard Lowe ret = errno;
3608d2a70789SRichard Lowe goto out;
3609d2a70789SRichard Lowe }
3610d2a70789SRichard Lowe
3611d2a70789SRichard Lowe if (psecflags(P_PID, P_MYID, PSF_UPPER,
3612d2a70789SRichard Lowe &cip->def_secflags.ss_upper) != 0) {
3613d2a70789SRichard Lowe *fp = "psecflags (default upper)";
3614d2a70789SRichard Lowe ret = errno;
3615d2a70789SRichard Lowe goto out;
3616d2a70789SRichard Lowe }
3617d2a70789SRichard Lowe
3618d2a70789SRichard Lowe if (psecflags(P_PID, P_MYID, PSF_INHERIT,
3619d2a70789SRichard Lowe &cip->secflag_delta) != 0) {
3620d2a70789SRichard Lowe *fp = "psecflags (from manifest)";
3621d2a70789SRichard Lowe ret = errno;
3622d2a70789SRichard Lowe goto out;
3623d2a70789SRichard Lowe }
3624d2a70789SRichard Lowe
36257c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) {
36267c478bd9Sstevel@tonic-gate if (cip->project == NULL) {
36277c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) {
36287c478bd9Sstevel@tonic-gate switch (errno) {
36297c478bd9Sstevel@tonic-gate case EACCES:
36307c478bd9Sstevel@tonic-gate case EPERM:
36317c478bd9Sstevel@tonic-gate *fp = "settaskid";
36327c478bd9Sstevel@tonic-gate ret = errno;
36337c478bd9Sstevel@tonic-gate goto out;
36347c478bd9Sstevel@tonic-gate
36357c478bd9Sstevel@tonic-gate case EINVAL:
36367c478bd9Sstevel@tonic-gate default:
36377c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno);
36387c478bd9Sstevel@tonic-gate }
36397c478bd9Sstevel@tonic-gate }
36407c478bd9Sstevel@tonic-gate } else {
36417c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) {
36427c478bd9Sstevel@tonic-gate case 0:
36437c478bd9Sstevel@tonic-gate break;
36447c478bd9Sstevel@tonic-gate
36457c478bd9Sstevel@tonic-gate case ENOMEM:
36467c478bd9Sstevel@tonic-gate case ENOENT:
36477c478bd9Sstevel@tonic-gate *fp = NULL;
36487c478bd9Sstevel@tonic-gate goto out;
36497c478bd9Sstevel@tonic-gate
36507c478bd9Sstevel@tonic-gate case EIO:
36517c478bd9Sstevel@tonic-gate case EMFILE:
36527c478bd9Sstevel@tonic-gate case ENFILE:
36537c478bd9Sstevel@tonic-gate *fp = "getpwuid_r";
36547c478bd9Sstevel@tonic-gate goto out;
36557c478bd9Sstevel@tonic-gate
36567c478bd9Sstevel@tonic-gate default:
36577c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret);
36587c478bd9Sstevel@tonic-gate }
36597c478bd9Sstevel@tonic-gate
36607c478bd9Sstevel@tonic-gate *fp = "setproject";
36617c478bd9Sstevel@tonic-gate
36627c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name,
36637c478bd9Sstevel@tonic-gate TASK_NORMAL)) {
36647c478bd9Sstevel@tonic-gate case 0:
36657c478bd9Sstevel@tonic-gate break;
36667c478bd9Sstevel@tonic-gate
36677c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK:
36687c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL:
36697c478bd9Sstevel@tonic-gate ret = errno;
36707c478bd9Sstevel@tonic-gate goto out;
36717c478bd9Sstevel@tonic-gate
36727c478bd9Sstevel@tonic-gate default:
36737c478bd9Sstevel@tonic-gate ret = -1;
36747c478bd9Sstevel@tonic-gate goto out;
36757c478bd9Sstevel@tonic-gate }
36767c478bd9Sstevel@tonic-gate }
36777c478bd9Sstevel@tonic-gate
36787c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) {
36797c478bd9Sstevel@tonic-gate if (mypid == -1)
36807c478bd9Sstevel@tonic-gate mypid = getpid();
36817c478bd9Sstevel@tonic-gate
36827c478bd9Sstevel@tonic-gate *fp = "pool_set_binding";
36837c478bd9Sstevel@tonic-gate
36847c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID,
36857c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) {
36867c478bd9Sstevel@tonic-gate switch (pool_error()) {
36873ad28c1eSrm case POE_INVALID_SEARCH:
36887c478bd9Sstevel@tonic-gate ret = ENOENT;
36897c478bd9Sstevel@tonic-gate break;
36907c478bd9Sstevel@tonic-gate
36913ad28c1eSrm case POE_BADPARAM:
36923ad28c1eSrm ret = EINVAL;
36933ad28c1eSrm break;
36943ad28c1eSrm
36957c478bd9Sstevel@tonic-gate case POE_INVALID_CONF:
36967c478bd9Sstevel@tonic-gate ret = EBADF;
36977c478bd9Sstevel@tonic-gate break;
36987c478bd9Sstevel@tonic-gate
36997c478bd9Sstevel@tonic-gate case POE_SYSTEM:
37007c478bd9Sstevel@tonic-gate ret = -1;
37017c478bd9Sstevel@tonic-gate break;
37027c478bd9Sstevel@tonic-gate
37037c478bd9Sstevel@tonic-gate default:
37047c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding",
37057c478bd9Sstevel@tonic-gate pool_error());
37067c478bd9Sstevel@tonic-gate }
37077c478bd9Sstevel@tonic-gate
37087c478bd9Sstevel@tonic-gate goto out;
37097c478bd9Sstevel@tonic-gate }
37107c478bd9Sstevel@tonic-gate }
37117c478bd9Sstevel@tonic-gate }
37127c478bd9Sstevel@tonic-gate
37137c478bd9Sstevel@tonic-gate /*
37142a3221a4Svp * Now, we have to assume our ID. If the UID is 0, we want it to be
37152a3221a4Svp * privilege-aware, otherwise the limit set gets used instead of E/P.
37167c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps
37177c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()).
37187c478bd9Sstevel@tonic-gate */
37197c478bd9Sstevel@tonic-gate
372013d8aaa1SSean Wilcox *fp = "setppriv";
372113d8aaa1SSean Wilcox
372213d8aaa1SSean Wilcox if (cip->lpriv_set != NULL) {
372313d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) {
372413d8aaa1SSean Wilcox ret = errno;
372513d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM);
372613d8aaa1SSean Wilcox goto out;
372713d8aaa1SSean Wilcox }
372813d8aaa1SSean Wilcox }
372913d8aaa1SSean Wilcox if (cip->priv_set != NULL) {
373013d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) {
373113d8aaa1SSean Wilcox ret = errno;
373213d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM);
373313d8aaa1SSean Wilcox goto out;
373413d8aaa1SSean Wilcox }
373513d8aaa1SSean Wilcox }
373613d8aaa1SSean Wilcox
373713d8aaa1SSean Wilcox /*
373813d8aaa1SSean Wilcox * If the limit privset is already set, then must be privilege
373913d8aaa1SSean Wilcox * aware. Otherwise, don't assume anything, and force privilege
374013d8aaa1SSean Wilcox * aware status.
374113d8aaa1SSean Wilcox */
374213d8aaa1SSean Wilcox
374313d8aaa1SSean Wilcox if (cip->lpriv_set == NULL && cip->priv_set != NULL) {
374413d8aaa1SSean Wilcox ret = setpflags(PRIV_AWARE, 1);
374513d8aaa1SSean Wilcox assert(ret == 0);
374613d8aaa1SSean Wilcox }
374713d8aaa1SSean Wilcox
37487c478bd9Sstevel@tonic-gate *fp = "setreuid";
3749f48205beScasper if (setreuid(cip->uid,
3750f48205beScasper cip->euid != (uid_t)-1 ? cip->euid : cip->uid) != 0) {
37517c478bd9Sstevel@tonic-gate ret = errno;
37527c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM);
37537c478bd9Sstevel@tonic-gate goto out;
37547c478bd9Sstevel@tonic-gate }
37557c478bd9Sstevel@tonic-gate
37567c478bd9Sstevel@tonic-gate *fp = "setppriv";
37577c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) {
37587c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) {
37597c478bd9Sstevel@tonic-gate ret = errno;
37607c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM);
37617c478bd9Sstevel@tonic-gate goto out;
37627c478bd9Sstevel@tonic-gate }
37637c478bd9Sstevel@tonic-gate }
37647c478bd9Sstevel@tonic-gate
37652a3221a4Svp /*
37662a3221a4Svp * The last thing to do is chdir to the specified working directory.
37672a3221a4Svp * This should come after the uid switching as only the user might
37682a3221a4Svp * have access to the specified directory.
37692a3221a4Svp */
37702a3221a4Svp if (cip->working_dir != NULL) {
37713eae19d9Swesolows do {
37722a3221a4Svp r = chdir(cip->working_dir);
37733eae19d9Swesolows } while (r != 0 && errno == EINTR);
37742a3221a4Svp if (r != 0) {
37752a3221a4Svp *fp = "chdir";
37762a3221a4Svp ret = errno;
37772a3221a4Svp goto out;
37782a3221a4Svp }
37792a3221a4Svp }
37802a3221a4Svp
37817c478bd9Sstevel@tonic-gate ret = 0;
37827c478bd9Sstevel@tonic-gate out:
37837c478bd9Sstevel@tonic-gate free(cip->pwbuf);
37847c478bd9Sstevel@tonic-gate cip->pwbuf = NULL;
37857c478bd9Sstevel@tonic-gate return (ret);
37867c478bd9Sstevel@tonic-gate }
37877c478bd9Sstevel@tonic-gate
37887c478bd9Sstevel@tonic-gate void
restarter_free_method_context(struct method_context * mcp)37897c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp)
37907c478bd9Sstevel@tonic-gate {
37917c478bd9Sstevel@tonic-gate size_t i;
37927c478bd9Sstevel@tonic-gate
37937c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL)
37947c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set);
37957c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL)
37967c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set);
37977c478bd9Sstevel@tonic-gate
37987c478bd9Sstevel@tonic-gate if (mcp->env != NULL) {
37997c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++)
38007c478bd9Sstevel@tonic-gate free(mcp->env[i]);
38017c478bd9Sstevel@tonic-gate free(mcp->env);
38027c478bd9Sstevel@tonic-gate }
38037c478bd9Sstevel@tonic-gate
38047c478bd9Sstevel@tonic-gate free(mcp->working_dir);
38057c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern);
38067c478bd9Sstevel@tonic-gate free(mcp->project);
38077c478bd9Sstevel@tonic-gate free(mcp->resource_pool);
38087c478bd9Sstevel@tonic-gate free(mcp);
38097c478bd9Sstevel@tonic-gate }
38107c478bd9Sstevel@tonic-gate
38117c478bd9Sstevel@tonic-gate /*
38127c478bd9Sstevel@tonic-gate * Method keyword functions
38137c478bd9Sstevel@tonic-gate */
38147c478bd9Sstevel@tonic-gate
38157c478bd9Sstevel@tonic-gate int
restarter_is_null_method(const char * meth)38167c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth)
38177c478bd9Sstevel@tonic-gate {
38187c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0);
38197c478bd9Sstevel@tonic-gate }
38207c478bd9Sstevel@tonic-gate
38217c478bd9Sstevel@tonic-gate static int
is_kill_method(const char * method,const char * kill_str,size_t kill_str_len)38227c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str,
38237c478bd9Sstevel@tonic-gate size_t kill_str_len)
38247c478bd9Sstevel@tonic-gate {
38257c478bd9Sstevel@tonic-gate const char *cp;
38267c478bd9Sstevel@tonic-gate int sig;
38277c478bd9Sstevel@tonic-gate
38287c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 ||
38297c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' &&
38307c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len])))
38317c478bd9Sstevel@tonic-gate return (-1);
38327c478bd9Sstevel@tonic-gate
38337c478bd9Sstevel@tonic-gate cp = method + kill_str_len;
38347c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp))
38357c478bd9Sstevel@tonic-gate ++cp;
38367c478bd9Sstevel@tonic-gate
38377c478bd9Sstevel@tonic-gate if (*cp == '\0')
38387c478bd9Sstevel@tonic-gate return (SIGTERM);
38397c478bd9Sstevel@tonic-gate
38407c478bd9Sstevel@tonic-gate if (*cp != '-')
38417c478bd9Sstevel@tonic-gate return (-1);
38427c478bd9Sstevel@tonic-gate
38437c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1);
38447c478bd9Sstevel@tonic-gate }
38457c478bd9Sstevel@tonic-gate
38467c478bd9Sstevel@tonic-gate int
restarter_is_kill_proc_method(const char * method)38477c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method)
38487c478bd9Sstevel@tonic-gate {
38497c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC,
38507c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1));
38517c478bd9Sstevel@tonic-gate }
38527c478bd9Sstevel@tonic-gate
38537c478bd9Sstevel@tonic-gate int
restarter_is_kill_method(const char * method)38547c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method)
38557c478bd9Sstevel@tonic-gate {
38567c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1));
38577c478bd9Sstevel@tonic-gate }
38587c478bd9Sstevel@tonic-gate
38597c478bd9Sstevel@tonic-gate /*
38607c478bd9Sstevel@tonic-gate * Stubs for now.
38617c478bd9Sstevel@tonic-gate */
38627c478bd9Sstevel@tonic-gate
38637c478bd9Sstevel@tonic-gate /* ARGSUSED */
38647c478bd9Sstevel@tonic-gate int
restarter_event_get_enabled(restarter_event_t * e)38657c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e)
38667c478bd9Sstevel@tonic-gate {
38677c478bd9Sstevel@tonic-gate return (-1);
38687c478bd9Sstevel@tonic-gate }
38697c478bd9Sstevel@tonic-gate
38707c478bd9Sstevel@tonic-gate /* ARGSUSED */
38717c478bd9Sstevel@tonic-gate uint64_t
restarter_event_get_seq(restarter_event_t * e)38727c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e)
38737c478bd9Sstevel@tonic-gate {
38747c478bd9Sstevel@tonic-gate return (-1);
38757c478bd9Sstevel@tonic-gate }
38767c478bd9Sstevel@tonic-gate
38777c478bd9Sstevel@tonic-gate /* ARGSUSED */
38787c478bd9Sstevel@tonic-gate void
restarter_event_get_time(restarter_event_t * e,hrtime_t * time)38797c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time)
38807c478bd9Sstevel@tonic-gate {
38817c478bd9Sstevel@tonic-gate }
3882eb1a3463STruong Nguyen
3883eb1a3463STruong Nguyen /*
3884eb1a3463STruong Nguyen * Check for and validate fmri specified in restarter_actions/auxiliary_fmri
3885eb1a3463STruong Nguyen * 0 - Success
3886eb1a3463STruong Nguyen * 1 - Failure
3887eb1a3463STruong Nguyen */
3888eb1a3463STruong Nguyen int
restarter_inst_validate_ractions_aux_fmri(scf_instance_t * inst)3889eb1a3463STruong Nguyen restarter_inst_validate_ractions_aux_fmri(scf_instance_t *inst)
3890eb1a3463STruong Nguyen {
3891eb1a3463STruong Nguyen scf_handle_t *h;
3892eb1a3463STruong Nguyen scf_propertygroup_t *pg;
3893eb1a3463STruong Nguyen scf_property_t *prop;
3894eb1a3463STruong Nguyen scf_value_t *val;
3895eb1a3463STruong Nguyen char *aux_fmri;
3896eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3897eb1a3463STruong Nguyen int ret = 1;
3898eb1a3463STruong Nguyen
3899eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL)
3900eb1a3463STruong Nguyen return (1);
3901eb1a3463STruong Nguyen
3902eb1a3463STruong Nguyen h = scf_instance_handle(inst);
3903eb1a3463STruong Nguyen
3904eb1a3463STruong Nguyen pg = scf_pg_create(h);
3905eb1a3463STruong Nguyen prop = scf_property_create(h);
3906eb1a3463STruong Nguyen val = scf_value_create(h);
3907eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL)
3908eb1a3463STruong Nguyen goto out;
3909eb1a3463STruong Nguyen
3910eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
3911eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
3912eb1a3463STruong Nguyen pg) != SCF_SUCCESS)
3913eb1a3463STruong Nguyen goto out;
3914eb1a3463STruong Nguyen
3915eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size,
3916eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS)
3917eb1a3463STruong Nguyen goto out;
3918eb1a3463STruong Nguyen
3919eb1a3463STruong Nguyen if (scf_parse_fmri(aux_fmri, NULL, NULL, NULL, NULL, NULL,
3920eb1a3463STruong Nguyen NULL) != SCF_SUCCESS)
3921eb1a3463STruong Nguyen goto out;
3922eb1a3463STruong Nguyen
3923eb1a3463STruong Nguyen ret = 0;
3924eb1a3463STruong Nguyen
3925eb1a3463STruong Nguyen out:
3926eb1a3463STruong Nguyen free(aux_fmri);
3927eb1a3463STruong Nguyen scf_value_destroy(val);
3928eb1a3463STruong Nguyen scf_property_destroy(prop);
3929eb1a3463STruong Nguyen scf_pg_destroy(pg);
3930eb1a3463STruong Nguyen return (ret);
3931eb1a3463STruong Nguyen }
3932eb1a3463STruong Nguyen
3933eb1a3463STruong Nguyen /*
3934eb1a3463STruong Nguyen * Get instance's boolean value in restarter_actions/auxiliary_tty
3935eb1a3463STruong Nguyen * Return -1 on failure
3936eb1a3463STruong Nguyen */
3937eb1a3463STruong Nguyen int
restarter_inst_ractions_from_tty(scf_instance_t * inst)3938eb1a3463STruong Nguyen restarter_inst_ractions_from_tty(scf_instance_t *inst)
3939eb1a3463STruong Nguyen {
3940eb1a3463STruong Nguyen scf_handle_t *h;
3941eb1a3463STruong Nguyen scf_propertygroup_t *pg;
3942eb1a3463STruong Nguyen scf_property_t *prop;
3943eb1a3463STruong Nguyen scf_value_t *val;
3944eb1a3463STruong Nguyen uint8_t has_tty;
3945eb1a3463STruong Nguyen int ret = -1;
3946eb1a3463STruong Nguyen
3947eb1a3463STruong Nguyen h = scf_instance_handle(inst);
3948eb1a3463STruong Nguyen pg = scf_pg_create(h);
3949eb1a3463STruong Nguyen prop = scf_property_create(h);
3950eb1a3463STruong Nguyen val = scf_value_create(h);
3951eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL)
3952eb1a3463STruong Nguyen goto out;
3953eb1a3463STruong Nguyen
3954eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
3955eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
3956eb1a3463STruong Nguyen pg) != SCF_SUCCESS)
3957eb1a3463STruong Nguyen goto out;
3958eb1a3463STruong Nguyen
3959eb1a3463STruong Nguyen if (get_boolean_val(pg, SCF_PROPERTY_AUX_TTY, &has_tty, prop,
3960eb1a3463STruong Nguyen val) != SCF_SUCCESS)
3961eb1a3463STruong Nguyen goto out;
3962eb1a3463STruong Nguyen
3963eb1a3463STruong Nguyen ret = has_tty;
3964eb1a3463STruong Nguyen
3965eb1a3463STruong Nguyen out:
3966eb1a3463STruong Nguyen scf_value_destroy(val);
3967eb1a3463STruong Nguyen scf_property_destroy(prop);
3968eb1a3463STruong Nguyen scf_pg_destroy(pg);
3969eb1a3463STruong Nguyen return (ret);
3970eb1a3463STruong Nguyen }
3971eb1a3463STruong Nguyen
3972ac0324d2SJerry Jelinek /*
3973ac0324d2SJerry Jelinek * If the instance's dump-on-restart property exists, remove it and return true,
3974ac0324d2SJerry Jelinek * otherwise return false.
3975ac0324d2SJerry Jelinek */
3976ac0324d2SJerry Jelinek int
restarter_inst_dump(scf_instance_t * inst)3977ac0324d2SJerry Jelinek restarter_inst_dump(scf_instance_t *inst)
3978ac0324d2SJerry Jelinek {
3979ac0324d2SJerry Jelinek scf_handle_t *h;
3980ac0324d2SJerry Jelinek scf_propertygroup_t *pg;
3981ac0324d2SJerry Jelinek scf_property_t *prop;
3982ac0324d2SJerry Jelinek scf_value_t *val;
3983ac0324d2SJerry Jelinek int ret = 0;
3984ac0324d2SJerry Jelinek
3985ac0324d2SJerry Jelinek h = scf_instance_handle(inst);
3986ac0324d2SJerry Jelinek pg = scf_pg_create(h);
3987ac0324d2SJerry Jelinek prop = scf_property_create(h);
3988ac0324d2SJerry Jelinek val = scf_value_create(h);
3989ac0324d2SJerry Jelinek if (pg == NULL || prop == NULL || val == NULL)
3990ac0324d2SJerry Jelinek goto out;
3991ac0324d2SJerry Jelinek
3992ac0324d2SJerry Jelinek if (scf_instance_get_pg(inst, SCF_PG_RESTARTER_ACTIONS, pg) !=
3993ac0324d2SJerry Jelinek SCF_SUCCESS) {
3994ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
3995ac0324d2SJerry Jelinek uu_die(rcbroken);
3996ac0324d2SJerry Jelinek goto out;
3997ac0324d2SJerry Jelinek }
3998ac0324d2SJerry Jelinek
3999ac0324d2SJerry Jelinek if (scf_pg_get_property(pg, SCF_PROPERTY_DODUMP, prop) != SCF_SUCCESS) {
4000ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
4001ac0324d2SJerry Jelinek uu_die(rcbroken);
4002ac0324d2SJerry Jelinek goto out;
4003ac0324d2SJerry Jelinek }
4004ac0324d2SJerry Jelinek
4005ac0324d2SJerry Jelinek ret = 1;
4006ac0324d2SJerry Jelinek
4007ac0324d2SJerry Jelinek if (scf_instance_delete_prop(inst, SCF_PG_RESTARTER_ACTIONS,
4008ac0324d2SJerry Jelinek SCF_PROPERTY_DODUMP) != SCF_SUCCESS) {
4009ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
4010ac0324d2SJerry Jelinek uu_die(rcbroken);
4011ac0324d2SJerry Jelinek goto out;
4012ac0324d2SJerry Jelinek }
4013ac0324d2SJerry Jelinek
4014ac0324d2SJerry Jelinek out:
4015ac0324d2SJerry Jelinek scf_value_destroy(val);
4016ac0324d2SJerry Jelinek scf_property_destroy(prop);
4017ac0324d2SJerry Jelinek scf_pg_destroy(pg);
4018ac0324d2SJerry Jelinek return (ret);
4019ac0324d2SJerry Jelinek }
4020ac0324d2SJerry Jelinek
4021eb1a3463STruong Nguyen static int
restarter_inst_set_astring_prop(scf_instance_t * inst,const char * pgname,const char * pgtype,uint32_t pgflags,const char * pname,const char * str)4022eb1a3463STruong Nguyen restarter_inst_set_astring_prop(scf_instance_t *inst, const char *pgname,
4023eb1a3463STruong Nguyen const char *pgtype, uint32_t pgflags, const char *pname, const char *str)
4024eb1a3463STruong Nguyen {
4025eb1a3463STruong Nguyen scf_handle_t *h;
4026eb1a3463STruong Nguyen scf_propertygroup_t *pg;
4027eb1a3463STruong Nguyen scf_transaction_t *t;
4028eb1a3463STruong Nguyen scf_transaction_entry_t *e;
4029eb1a3463STruong Nguyen scf_value_t *v;
4030eb1a3463STruong Nguyen int ret = 1, r;
4031eb1a3463STruong Nguyen
4032eb1a3463STruong Nguyen h = scf_instance_handle(inst);
4033eb1a3463STruong Nguyen
4034eb1a3463STruong Nguyen pg = scf_pg_create(h);
4035eb1a3463STruong Nguyen t = scf_transaction_create(h);
4036eb1a3463STruong Nguyen e = scf_entry_create(h);
4037eb1a3463STruong Nguyen v = scf_value_create(h);
4038eb1a3463STruong Nguyen if (pg == NULL || t == NULL || e == NULL || v == NULL)
4039eb1a3463STruong Nguyen goto out;
4040eb1a3463STruong Nguyen
4041eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, pgname, pgtype, pgflags, pg))
4042eb1a3463STruong Nguyen goto out;
4043eb1a3463STruong Nguyen
4044eb1a3463STruong Nguyen if (scf_value_set_astring(v, str) != SCF_SUCCESS)
4045eb1a3463STruong Nguyen goto out;
4046eb1a3463STruong Nguyen
4047eb1a3463STruong Nguyen for (;;) {
4048eb1a3463STruong Nguyen if (scf_transaction_start(t, pg) != 0)
4049eb1a3463STruong Nguyen goto out;
4050eb1a3463STruong Nguyen
4051eb1a3463STruong Nguyen if (tx_set_value(t, e, pname, SCF_TYPE_ASTRING, v) != 0)
4052eb1a3463STruong Nguyen goto out;
4053eb1a3463STruong Nguyen
4054eb1a3463STruong Nguyen if ((r = scf_transaction_commit(t)) == 1)
4055eb1a3463STruong Nguyen break;
4056eb1a3463STruong Nguyen
4057eb1a3463STruong Nguyen if (r == -1)
4058eb1a3463STruong Nguyen goto out;
4059eb1a3463STruong Nguyen
4060eb1a3463STruong Nguyen scf_transaction_reset(t);
4061eb1a3463STruong Nguyen if (scf_pg_update(pg) == -1)
4062eb1a3463STruong Nguyen goto out;
4063eb1a3463STruong Nguyen }
4064eb1a3463STruong Nguyen ret = 0;
4065eb1a3463STruong Nguyen
4066eb1a3463STruong Nguyen out:
4067eb1a3463STruong Nguyen scf_transaction_destroy(t);
4068eb1a3463STruong Nguyen scf_entry_destroy(e);
4069eb1a3463STruong Nguyen scf_value_destroy(v);
4070eb1a3463STruong Nguyen scf_pg_destroy(pg);
4071eb1a3463STruong Nguyen
4072eb1a3463STruong Nguyen return (ret);
4073eb1a3463STruong Nguyen }
4074eb1a3463STruong Nguyen
4075eb1a3463STruong Nguyen int
restarter_inst_set_aux_fmri(scf_instance_t * inst)4076eb1a3463STruong Nguyen restarter_inst_set_aux_fmri(scf_instance_t *inst)
4077eb1a3463STruong Nguyen {
4078eb1a3463STruong Nguyen scf_handle_t *h;
4079eb1a3463STruong Nguyen scf_propertygroup_t *pg;
4080eb1a3463STruong Nguyen scf_property_t *prop;
4081eb1a3463STruong Nguyen scf_value_t *val;
4082eb1a3463STruong Nguyen char *aux_fmri;
4083eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
4084eb1a3463STruong Nguyen int ret = 1;
4085eb1a3463STruong Nguyen
4086eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL)
4087eb1a3463STruong Nguyen return (1);
4088eb1a3463STruong Nguyen
4089eb1a3463STruong Nguyen h = scf_instance_handle(inst);
4090eb1a3463STruong Nguyen
4091eb1a3463STruong Nguyen pg = scf_pg_create(h);
4092eb1a3463STruong Nguyen prop = scf_property_create(h);
4093eb1a3463STruong Nguyen val = scf_value_create(h);
4094eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL)
4095eb1a3463STruong Nguyen goto out;
4096eb1a3463STruong Nguyen
4097eb1a3463STruong Nguyen /*
4098eb1a3463STruong Nguyen * Get auxiliary_fmri value from restarter_actions pg
4099eb1a3463STruong Nguyen */
4100eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
4101eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
4102eb1a3463STruong Nguyen pg) != SCF_SUCCESS)
4103eb1a3463STruong Nguyen goto out;
4104eb1a3463STruong Nguyen
4105eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size,
4106eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS)
4107eb1a3463STruong Nguyen goto out;
4108eb1a3463STruong Nguyen
4109eb1a3463STruong Nguyen /*
4110eb1a3463STruong Nguyen * Populate restarter/auxiliary_fmri with the obtained fmri.
4111eb1a3463STruong Nguyen */
4112eb1a3463STruong Nguyen ret = restarter_inst_set_astring_prop(inst, SCF_PG_RESTARTER,
4113eb1a3463STruong Nguyen SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS,
4114eb1a3463STruong Nguyen SCF_PROPERTY_AUX_FMRI, aux_fmri);
4115eb1a3463STruong Nguyen
4116eb1a3463STruong Nguyen out:
4117eb1a3463STruong Nguyen free(aux_fmri);
4118eb1a3463STruong Nguyen scf_value_destroy(val);
4119eb1a3463STruong Nguyen scf_property_destroy(prop);
4120eb1a3463STruong Nguyen scf_pg_destroy(pg);
4121eb1a3463STruong Nguyen return (ret);
4122eb1a3463STruong Nguyen }
4123eb1a3463STruong Nguyen
4124eb1a3463STruong Nguyen int
restarter_inst_reset_aux_fmri(scf_instance_t * inst)4125eb1a3463STruong Nguyen restarter_inst_reset_aux_fmri(scf_instance_t *inst)
4126eb1a3463STruong Nguyen {
4127eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst,
4128eb1a3463STruong Nguyen SCF_PG_RESTARTER, SCF_PROPERTY_AUX_FMRI));
4129eb1a3463STruong Nguyen }
4130eb1a3463STruong Nguyen
4131eb1a3463STruong Nguyen int
restarter_inst_reset_ractions_aux_fmri(scf_instance_t * inst)4132eb1a3463STruong Nguyen restarter_inst_reset_ractions_aux_fmri(scf_instance_t *inst)
4133eb1a3463STruong Nguyen {
4134eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst,
4135eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI));
4136eb1a3463STruong Nguyen }
4137