1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2017 RackTop Systems.
24 */
25
26 #ifndef _LIBRESTART_H
27 #define _LIBRESTART_H
28
29 #include <libsysevent.h>
30 #include <libcontract.h>
31 #include <libscf.h>
32 #include <limits.h>
33 #include <priv.h>
34 #include <pwd.h>
35 #include <sys/types.h>
36 #include <sys/secflags.h>
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 /*
43 * There are 3 parts to librestart.
44 * 1) The event protocol from the master restarter to its delegates.
45 * 2) A functional interface for updating the repository.
46 * 3) Convenience functions for common restarter tasks.
47 *
48 * Event protocol
49 * We need a reliable event protocol, as there's no way to define
50 * restarter events as idempotent.
51 *
52 * Currently using sysevent channels as the reliable event implementation.
53 * This could change if the implementation proves unsuitable, but
54 * the API defined here should abstract anything but a change in
55 * the fundamental event model.
56 *
57 * We offer functions to tease apart the event rather than generic
58 * nvpair interfaces. This is because each event type has a well-
59 * defined set of fields.
60 */
61
62 /*
63 * Some of the functions have external contracted consumers, review contracts
64 * when making incompatible changes.
65 */
66
67 typedef struct restarter_event_handle restarter_event_handle_t;
68 typedef struct restarter_event restarter_event_t;
69
70 typedef uint32_t restarter_event_type_t;
71
72 /*
73 * Define an event protocol version. In theory, we could use this in
74 * the future to support delegated restarters which use an older
75 * protocol. In practice, increment RESTARTER_EVENT_VERSION whenever the
76 * protocol might have changed.
77 */
78 #define RESTARTER_EVENT_VERSION 5
79
80 #define RESTARTER_FLAG_DEBUG 1
81
82 #define RESTARTER_ERRMSGSZ 1024
83
84 /*
85 * Event types
86 * RESTARTER_EVENT_TYPE_ADD_INSTANCE
87 * responsible for a new (stopped) instance
88 * RESTARTER_EVENT_TYPE_REMOVE_INSTANCE
89 * no longer responsible for this instance; stop it and return
90 * RESTARTER_EVENT_TYPE_ENABLE
91 * no guarantee that dependencies are met; see
92 * RESTARTER_EVENT_TYPE_START
93 * RESTARTER_EVENT_TYPE_DISABLE
94 * no guarantee that instance was running
95 * RESTARTER_EVENT_TYPE_ADMIN_RESTORE
96 * RESTARTER_EVENT_TYPE_ADMIN_DEGRADED
97 * RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE
98 * RESTARTER_EVENT_TYPE_ADMIN_REFRESH
99 * RESTARTER_EVENT_TYPE_ADMIN_RESTART
100 * RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
101 * RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
102 * RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE
103 * RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
104 * RESTARTER_EVENT_TYPE_STOP
105 * dependencies are, or are becoming, unsatisfied
106 * RESTARTER_EVENT_TYPE_START
107 * dependencies have become satisfied
108 * RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
109 * instance caused a dependency cycle
110 * RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
111 * instance has an invalid dependency
112 */
113
114 #define RESTARTER_EVENT_TYPE_INVALID 0
115 #define RESTARTER_EVENT_TYPE_ADD_INSTANCE 1
116 #define RESTARTER_EVENT_TYPE_REMOVE_INSTANCE 2
117 #define RESTARTER_EVENT_TYPE_ENABLE 3
118 #define RESTARTER_EVENT_TYPE_DISABLE 4
119 #define RESTARTER_EVENT_TYPE_ADMIN_DEGRADED 5
120 #define RESTARTER_EVENT_TYPE_ADMIN_REFRESH 6
121 #define RESTARTER_EVENT_TYPE_ADMIN_RESTART 7
122 #define RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF 8
123 #define RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON 9
124 #define RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE 10
125 #define RESTARTER_EVENT_TYPE_STOP 11
126 #define RESTARTER_EVENT_TYPE_START 12
127 #define RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE 13
128 #define RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY 14
129 #define RESTARTER_EVENT_TYPE_ADMIN_DISABLE 15
130 #define RESTARTER_EVENT_TYPE_STOP_RESET 16
131 #define RESTARTER_EVENT_TYPE_ADMIN_RESTORE 17
132 #define RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE 18
133
134 #define RESTARTER_EVENT_ERROR -1
135
136 #define RESTARTER_EVENT_INSTANCE_DISABLED 0
137 #define RESTARTER_EVENT_INSTANCE_ENABLED 1
138
139 typedef enum {
140 RESTARTER_STATE_NONE,
141 RESTARTER_STATE_UNINIT,
142 RESTARTER_STATE_MAINT,
143 RESTARTER_STATE_OFFLINE,
144 RESTARTER_STATE_DISABLED,
145 RESTARTER_STATE_ONLINE,
146 RESTARTER_STATE_DEGRADED
147 } restarter_instance_state_t;
148
149 /*
150 * These values are ordered by severity of required restart, as we use
151 * integer comparisons to determine error flow.
152 */
153 typedef enum {
154 RERR_UNSUPPORTED = -1,
155 RERR_NONE = 0, /* no error, restart, refresh */
156 RERR_FAULT, /* fault occurred */
157 RERR_RESTART, /* transition due to restart */
158 RERR_REFRESH /* transition due to refresh */
159 } restarter_error_t;
160 /*
161 * restarter_store_contract() and restarter_remove_contract() types
162 */
163 typedef enum {
164 RESTARTER_CONTRACT_PRIMARY,
165 RESTARTER_CONTRACT_TRANSIENT
166 } restarter_contract_type_t;
167
168 /*
169 * restarter_bind_handle() registers a delegate with svc.startd to
170 * begin consuming events.
171 *
172 * On initial bind, the delgated restarter receives an event for each
173 * instance it is responsible for, as if that instance was new.
174 *
175 * callers must have superuser privileges
176 *
177 * The event handler can return 0 for success, or EAGAIN to request
178 * retry of event delivery. EAGAIN may be returned 3 times before the
179 * event is discarded.
180 */
181 int restarter_bind_handle(uint32_t, const char *,
182 int (*event_handler)(restarter_event_t *), int,
183 restarter_event_handle_t **);
184
185 restarter_event_type_t restarter_event_get_type(restarter_event_t *);
186 uint64_t restarter_event_get_seq(restarter_event_t *);
187 void restarter_event_get_time(restarter_event_t *, hrtime_t *);
188 ssize_t restarter_event_get_instance(restarter_event_t *, char *, size_t);
189 restarter_event_handle_t *restarter_event_get_handle(restarter_event_t *);
190
191 /*
192 * The following functions work only on certain types of events.
193 * They fail with a return of -1 if they're called on an inappropriate event.
194 */
195 int restarter_event_get_enabled(restarter_event_t *);
196 int restarter_event_get_current_states(restarter_event_t *,
197 restarter_instance_state_t *, restarter_instance_state_t *);
198
199 /*
200 * State transition reasons
201 */
202
203 typedef enum {
204 restarter_str_none,
205 restarter_str_administrative_request,
206 restarter_str_bad_repo_state,
207 restarter_str_clear_request,
208 restarter_str_ct_ev_core,
209 restarter_str_ct_ev_exit,
210 restarter_str_ct_ev_hwerr,
211 restarter_str_ct_ev_signal,
212 restarter_str_dependencies_satisfied,
213 restarter_str_dependency_activity,
214 restarter_str_dependency_cycle,
215 restarter_str_disable_request,
216 restarter_str_enable_request,
217 restarter_str_fault_threshold_reached,
218 restarter_str_insert_in_graph,
219 restarter_str_invalid_dependency,
220 restarter_str_invalid_restarter,
221 restarter_str_method_failed,
222 restarter_str_per_configuration,
223 restarter_str_refresh,
224 restarter_str_restart_request,
225 restarter_str_restarting_too_quickly,
226 restarter_str_service_request,
227 restarter_str_startd_restart
228 } restarter_str_t;
229
230 struct restarter_state_transition_reason {
231 restarter_str_t str_key;
232 const char *str_short;
233 const char *str_long;
234 };
235
236 /*
237 * Functions for updating the repository.
238 */
239
240 /*
241 * When setting state to "maintenance", callers of restarter_set_states() can
242 * set aux_state to "service_request" to communicate that another service has
243 * requested maintenance state for the target service.
244 *
245 * Callers should use restarter_inst_validate_aux_fmri() to validate the fmri
246 * of the requested service and pass "service_request" for aux_state when
247 * calling restarter_set_states(). See inetd and startd for examples.
248 */
249 int restarter_set_states(restarter_event_handle_t *, const char *,
250 restarter_instance_state_t, restarter_instance_state_t,
251 restarter_instance_state_t, restarter_instance_state_t, restarter_error_t,
252 restarter_str_t);
253 int restarter_event_publish_retry(evchan_t *, const char *, const char *,
254 const char *, const char *, nvlist_t *, uint32_t);
255
256 /*
257 * functions for retrieving the state transition reason messages
258 */
259
260 #define RESTARTER_STRING_VERSION 1
261
262 uint32_t restarter_str_version(void);
263 const char *restarter_get_str_short(restarter_str_t);
264 const char *restarter_get_str_long(restarter_str_t);
265
266 int restarter_store_contract(scf_instance_t *, ctid_t,
267 restarter_contract_type_t);
268 int restarter_remove_contract(scf_instance_t *, ctid_t,
269 restarter_contract_type_t);
270
271 ssize_t restarter_state_to_string(restarter_instance_state_t, char *, size_t);
272 restarter_instance_state_t restarter_string_to_state(char *);
273
274 #define RESTARTER_METHOD_CONTEXT_VERSION 8
275
276 struct method_context {
277 /* Stable */
278 uid_t uid, euid;
279 gid_t gid, egid;
280 int ngroups; /* -1 means use initgroups(). */
281 gid_t groups[NGROUPS_MAX];
282 scf_secflags_t def_secflags;
283 secflagdelta_t secflag_delta;
284 priv_set_t *lpriv_set, *priv_set;
285 char *corefile_pattern; /* Optional. */
286 char *project; /* NULL for no change */
287 char *resource_pool; /* NULL for project default */
288 char *working_dir; /* NULL for :default */
289 char **env; /* NULL for no env */
290 size_t env_sz; /* size of env array */
291
292 /* Private */
293 char *vbuf;
294 ssize_t vbuf_sz;
295 struct passwd pwd;
296 char *pwbuf;
297 ssize_t pwbufsz;
298 };
299
300 /*
301 * An error structure that contains a message string, and a type
302 * that can be used to determine course of action by the reciever
303 * of the error structure.
304 *
305 * type - usually will be an errno equivalent but could contain
306 * defined error types for exampe SCF_ERROR_XXX
307 * msg - must be at the end of the structure as if the message is
308 * longer than EMSGSIZE we will reallocate the structure to
309 * handle the overflow
310 */
311 typedef struct mc_error {
312 int destroy; /* Flag to indicate destruction steps */
313 int type; /* Type of error for decision making */
314 int size; /* The size of the error message string */
315 char msg[RESTARTER_ERRMSGSZ];
316 } mc_error_t;
317
318 int restarter_rm_libs_loadable(void);
319 /* instance, restarter name, method name, command line, structure pointer */
320 mc_error_t *restarter_get_method_context(uint_t, scf_instance_t *,
321 scf_snapshot_t *, const char *, const char *, struct method_context **);
322 void restarter_mc_error_destroy(mc_error_t *);
323 int restarter_set_method_context(struct method_context *, const char **);
324 void restarter_free_method_context(struct method_context *);
325
326
327 int restarter_is_null_method(const char *);
328 int restarter_is_kill_method(const char *);
329 int restarter_is_kill_proc_method(const char *);
330
331 /* Validate the inst fmri specified in restarter_actions/auxiliary_fmri */
332 int restarter_inst_validate_ractions_aux_fmri(scf_instance_t *);
333
334 /* Delete instance's restarter_actions/auxiliary_fmri property */
335 int restarter_inst_reset_ractions_aux_fmri(scf_instance_t *);
336
337 /* Get boolean value from instance's restarter_actions/auxiliary_tty */
338 int restarter_inst_ractions_from_tty(scf_instance_t *);
339
340 /* Delete instance's restarter/auxiliary_fmri property */
341 int restarter_inst_reset_aux_fmri(scf_instance_t *);
342
343 /* Get boolean value from instance's restarter_actions/do_dump */
344 int restarter_inst_dump(scf_instance_t *);
345
346 /*
347 * Set instance's restarter/auxiliary_fmri, value come from
348 * restarter_actions/auxliary_fmri
349 */
350 int restarter_inst_set_aux_fmri(scf_instance_t *);
351
352 #ifdef __cplusplus
353 }
354 #endif
355
356 #endif /* _LIBRESTART_H */