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 */