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