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