xref: /illumos-gate/usr/src/lib/librestart/common/librestart.h (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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_DEGRADED
96  *	RESTARTER_EVENT_TYPE_ADMIN_REFRESH
97  *	RESTARTER_EVENT_TYPE_ADMIN_RESTART
98  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
99  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
100  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE
101  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
102  *	RESTARTER_EVENT_TYPE_STOP
103  *		dependencies are, or are becoming, unsatisfied
104  *	RESTARTER_EVENT_TYPE_START
105  *		dependencies have become satisfied
106  *	RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
107  *		instance caused a dependency cycle
108  *	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
109  *		instance has an invalid dependency
110  *	RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE
111  *	RESTARTER_EVENT_TYPE_ADMIN_RESTORE
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_DEGRADE_IMMEDIATE	17
132 #define	RESTARTER_EVENT_TYPE_ADMIN_RESTORE		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 */
357