configd.h revision 6643e1ff9dc8f93c925c670fddd7a0a5b9fd4b29
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _CONFIGD_H
#define _CONFIGD_H
#pragma ident "%Z%%M% %I% %E% SMI"
#include <door.h>
#include <pthread.h>
#include <string.h>
#include <libscf.h>
#include <repcache_protocol.h>
#include <libuutil.h>
#include <configd_exit.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Lock order:
*
* client lock
* iter locks, in ID order
* entity locks, in ID order
*
* backend locks (NORMAL, then NONPERSIST)
* rc_node lock
* children's rc_node lock
* cache bucket lock
* rc_node lock[*]
*
* * only one node may be grabbed while holding a bucket lock
*
* leaf locks: (no other locks may be aquired while holding one)
* rc_pg_notify_lock
* rc_annotate_lock
*/
/*
* Returns the minimum size for a structure of type 't' such
* that it is safe to access field 'f'.
*/
#define offsetofend(t, f) (offsetof(t, f) + sizeof (((t *)0)->f))
/*
* We want MUTEX_HELD, but we also want pthreads. So we're stuck with this.
*/
struct _lwp_mutex_t;
extern int _mutex_held(struct _lwp_mutex_t *);
/*
* Maximum levels of composition.
*/
#define COMPOSITION_DEPTH 2
#define CONFIGD_CORE "core.%f.%t.%p"
#ifndef NDEBUG
#define bad_error(f, e) \
uu_warn("%s:%d: %s() returned bad error %d. Aborting.\n", \
abort()
#else
#endif
typedef enum backend_type {
BACKEND_TYPE_NORMAL = 0,
BACKEND_TYPE_TOTAL /* backend use only */
/*
* pre-declare rc_* types
*/
typedef struct rc_snapshot rc_snapshot_t;
typedef struct rc_snaplevel rc_snaplevel_t;
/*
* notification layer -- protected by rc_pg_notify_lock
*/
typedef struct rc_notify_info rc_notify_info_t;
typedef struct rc_notify_delete rc_notify_delete_t;
typedef struct rc_notify {
} rc_notify_t;
struct rc_notify_delete {
char rnd_fmri[REP_PROTOCOL_FMRI_LEN];
};
struct rc_notify_info {
const char *rni_namelist[RC_NOTIFY_MAX_NAMES];
const char *rni_typelist[RC_NOTIFY_MAX_NAMES];
int rni_flags;
int rni_waiters;
};
#define RC_NOTIFY_ACTIVE 0x00000001
#define RC_NOTIFY_DRAIN 0x00000002
#define RC_NOTIFY_EMPTYING 0x00000004
typedef struct rc_node_pg_notify {
int rnpn_fd;
/*
* cache layer
*/
/*
* The 'key' for the main object hash. main_id is the main object
* identifier. The rl_ids array contains:
*
* TYPE RL_IDS
* scope unused
* service unused
* instance {service_id}
* snapshot {service_id, instance_id}
* snaplevel {service_id, instance_id, name_id, snapshot_id}
* propertygroup {service_id, (instance_id or 0), (name_id or 0),
* (snapshot_id or 0), (l_id or 0)}
* property {service_id, (instance_id or 0), (name_id or 0),
* (snapshot_id or 0), (l_id or 0), pg_id, gen_id}
*/
#define ID_SERVICE 0
#define ID_INSTANCE 1
#define ID_NAME 2
#define ID_SNAPSHOT 3
#define ID_LEVEL 4
#define ID_PG 5
#define ID_GEN 6
#define MAX_IDS 7
typedef struct rc_node_lookup {
struct rc_node {
/*
* read-only data
*/
const char *rn_name;
/*
* type-specific state
* (if space becomes an issue, these can become a union)
*/
/*
* Used by instances, snapshots, and "composed property groups" only.
* These are the entities whose properties should appear composed when
* this entity is traversed by a composed iterator. 0 is the top-most
* entity, down to COMPOSITION_DEPTH - 1.
*/
/*
* used by property groups only
*/
const char *rn_type;
/*
* used by properties only
*/
const char *rn_values; /* protected by rn_lock */
/*
* used by snapshots only
*/
/*
* used by snaplevels only
*/
/*
* mutable state
*/
const char *rn_fmri;
/*
* external state (protected by hash chain lock)
*/
};
/*
* flag ordering:
* RC_DYING
* RC_NODE_CHILDREN_CHANGING
* RC_NODE_CREATING_CHILD
* RC_NODE_USING_PARENT
* RC_NODE_IN_TX
*
* RC_NODE_USING_PARENT is special, because it lets you proceed up the tree,
* in the reverse of the usual locking order. Because of this, there are
* limitations on what you can do while holding it. While holding
* RC_NODE_USING_PARENT, you may:
* bump or release your parent's reference count
* access fields in your parent
* hold RC_NODE_USING_PARENT in the parent, proceeding recursively.
*
* If you are only holding *one* node's RC_NODE_USING_PARENT, and:
* you are *not* proceeding recursively, you can hold your
* immediate parent's RC_NODE_CHILDREN_CHANGING flag.
* you hold your parent's RC_NODE_CHILDREN_CHANGING flag, you can add
* RC_NODE_IN_TX to your flags.
* you want to grab a flag in your parent, you must lock your parent,
* lock yourself, drop RC_NODE_USING_PARENT, unlock yourself,
* then proceed to manipulate the parent.
*/
/*
* RC_NODE_DEAD means that the node no longer represents data in the
* backend, and we should return _DELETED errors to clients who try to use
* it. Very much like a zombie process.
*
* RC_NODE_OLD also means that the node no longer represents data in the
* backend, but it's ok for clients to access it because we've loaded all of
* the children. (This only happens for transactional objects such as
* property groups and snapshots, where we guarantee a stable view once
* a reference is obtained.) When all client references are destroyed,
* however, the node should be destroyed.
*
* Though RC_NODE_DEAD is set by the rc_node_delete() code, it is also set
* by rc_node_no_client_refs() for RC_NODE_OLD nodes not long before
* they're destroyed.
*/
#define RC_NODE_DYING_FLAGS \
#define RC_NODE_WAITING_FLAGS \
typedef enum rc_auth_state {
RC_AUTH_UNKNOWN = 0, /* No checks done yet. */
RC_AUTH_FAILED, /* Authorization checked & failed. */
RC_AUTH_PASSED /* Authorization succeeded. */
/*
* Some authorization checks are performed in rc_node_setup_tx() in
* response to the REP_PROTOCOL_PROPERTYGRP_TX_START message. Other checks
* must wait until the actual transaction operations are received in the
* REP_PROTOCOL_PROPERTYGRP_TX_COMMIT message. This second set of checks
* is performed in rc_tx_commit(). rnp_auth_string and rnp_authorized in
* the following structure are used to hold the results of the
* authorization checking done in rc_node_setup_tx() for later use by
* rc_tx_commit().
*
* In client.c transactions are represented by rc_node_ptr structures which
* point to a property group rc_node_t. Thus, this is an appropriate place
* to hold authorization state.
*/
typedef struct rc_node_ptr {
const char *rnp_auth_string; /* authorization string */
char rnp_deleted; /* object was deleted */
#define NODE_PTR_NOT_HELD(npp) \
typedef int rc_iter_filter_func(rc_node_t *, void *);
typedef struct rc_node_iter {
int rni_clevel; /* index into rni_parent->rn_cchain[] */
/*
* for normal walks
*/
void *rni_filter_arg;
/*
* for value walks
*/
typedef struct rc_node_tx {
int rnt_authorized; /* No need to check anymore. */
} rc_node_tx_t;
typedef struct cache_bucket {
2 * sizeof (rc_node_t *)];
/*
* tx_commit_data_tx is an opaque structure which is defined in object.c.
* It contains the data of the transaction that is to be committed.
* Accessor functions in object.c allow other modules to retrieve
* information.
*/
typedef struct tx_commit_data tx_commit_data_t;
/*
* Snapshots
*/
struct rc_snapshot {
};
#define RC_SNAPSHOT_READY 0x00000002
typedef struct rc_snaplevel_pgs {
struct rc_snaplevel {
const char *rsl_scope;
const char *rsl_service;
const char *rsl_instance;
};
/*
* Client layer -- the IDs fields must be first, in order for the search
* routines to work correctly.
*/
enum repcache_txstate {
};
typedef struct repcache_entity {
typedef struct repcache_iter {
typedef struct repcache_client {
/*
* constants
*/
int rc_all_auths; /* bypass auth checks */
int rc_doorfd; /* our door's FD */
/*
* Constants used for security auditing
*
* rc_adt_session points to the audit session data that is used for
* the life of the client. rc_adt_sessionid is the session ID that
* is initially assigned when the audit session is started. See
* start_audit_session() in client.c. This session id is used for
* audit events except when we are processing a set of annotated
* events. Annotated events use a separate session id so that they
* can be grouped. See set_annotation() in client.c.
*/
/* auditing */
/*
* client list linkage, protected by hash chain lock
*/
/*
* notification information, protected by rc_node layer
*/
/*
* client_wait output, only usable by rc_notify_thr
*/
/*
* register sets, protected by rc_lock
*/
/*
* Variables, protected by rc_lock
*/
int rc_refcnt; /* in-progress door calls */
int rc_flags; /* see RC_CLIENT_* symbols below */
/*
* Per-client audit information. These fields must be protected by
* rc_annotate_lock separately from rc_lock because they may need
* to be accessed from rc_node.c with an entity or iterator lock
* held, and those must be taken after rc_lock.
*/
int rc_annotate; /* generate annotation event if set */
const char *rc_operation; /* operation for audit annotation */
const char *rc_file; /* file name for audit annotation */
/* Bit definitions for rc_flags. */
#define RC_CLIENT_DEAD 0x00000001
typedef struct client_bucket {
enum rc_ptr_type {
RC_PTR_TYPE_ENTITY = 1,
};
typedef struct request_log_ptr {
enum rc_ptr_type rlp_type;
void *rlp_ptr; /* repcache_{entity,iter}_t */
void *rlp_data; /* rc_node, for ENTITY only */
#define MAX_PTRS 3
/*
* rl_start through rl_client cannot move without changing start_log()
*/
typedef struct request_log_entry {
int rl_num_ptrs;
/*
* thread information
*/
typedef enum thread_state {
typedef struct thread_info {
/*
* per-thread globals
*/
int ti_ucred_read; /* ucred holds current creds */
/*
* per-thread state information, for debuggers
*/
struct rep_protocol_request *ti_client_request;
/*
* Backend layer
*/
typedef struct backend_query backend_query_t;
typedef struct backend_tx backend_tx_t;
/*
*/
thread_info_t *thread_self(void);
int ucred_is_privileged(ucred_t *);
adt_session_data_t *get_audit_session(void);
void configd_critical(const char *, ...);
void configd_vcritical(const char *, va_list);
void configd_info(const char *, ...);
extern int is_main_repository;
extern int max_repository_backups;
/*
*/
int setup_main_door(const char *);
/*
* client.c
*/
void client_annotation_finished(void);
int client_init(void);
int client_is_privileged(void);
void log_enter(request_log_entry_t *);
/*
*/
int rc_node_init();
int rc_check_type_name(uint32_t, const char *);
void rc_node_ptr_free_mem(rc_node_ptr_t *);
void rc_node_rele(rc_node_t *);
const char *, rc_node_t *);
rc_snaplevel_t *, rc_node_t *);
rc_node_t *rc_node_alloc(void);
void rc_node_destroy(rc_node_t *);
/*
* rc_node.c, client interface (rc_node_ptr_t, rc_node_iter_t)
*/
void rc_node_ptr_init(rc_node_ptr_t *);
void rc_node_clear(rc_node_ptr_t *, int);
struct rep_protocol_value_response *, size_t *);
rc_node_ptr_t *);
const char *, uint32_t, rc_node_ptr_t *);
int rc_node_update(rc_node_ptr_t *);
int rc_node_delete(rc_node_ptr_t *);
size_t, const char *);
size_t *, int);
void rc_iter_destroy(rc_node_iter_t **);
void rc_pg_notify_init(rc_node_pg_notify_t *);
void rc_pg_notify_fini(rc_node_pg_notify_t *);
void rc_notify_info_init(rc_notify_info_t *);
int rc_notify_info_add_name(rc_notify_info_t *, const char *);
int rc_notify_info_add_type(rc_notify_info_t *, const char *);
void rc_notify_info_fini(rc_notify_info_t *);
int rc_snapshot_take_new(rc_node_ptr_t *, const char *,
const char *, const char *, rc_node_ptr_t *);
/*
*/
int object_fill_children(rc_node_t *);
int object_delete(rc_node_t *);
int object_fill_snapshot(rc_snapshot_t *);
int object_snapshot_take_new(rc_node_t *, const char *, const char *,
const char *, rc_node_t **);
/*
* object.c
*/
/* Functions to access transaction commands. */
enum rep_protocol_transaction_action *);
void tx_commit_data_free(tx_commit_data_t *);
/*
*/
void rc_snapshot_rele(rc_snapshot_t *);
void rc_snaplevel_hold(rc_snaplevel_t *);
void rc_snaplevel_rele(rc_snaplevel_t *);
/*
*/
int backend_init(const char *, const char *, int);
void backend_fini(void);
rep_protocol_responseid_t backend_create_backup(const char *);
/*
* call on any database inconsistency -- cleans up state as best it can,
* and exits with a "Database Bad" error code.
*/
void backend_panic(const char *, ...) __NORETURN;
#pragma rarely_called(backend_panic)
backend_query_t *backend_query_alloc(void);
void backend_query_append(backend_query_t *, const char *);
void backend_query_add(backend_query_t *, const char *, ...);
void backend_query_free(backend_query_t *);
char **names);
#define BACKEND_CALLBACK_CONTINUE 0
#define BACKEND_CALLBACK_ABORT 1
backend_run_callback_f *, void *);
void backend_tx_end_ro(backend_tx_t *);
enum id_space {
BACKEND_ID_INVALID /* always illegal */
};
int backend_tx_run_update(backend_tx_t *, const char *, ...);
int backend_tx_run_update_changed(backend_tx_t *, const char *, ...);
backend_run_callback_f *, void *);
int backend_tx_commit(backend_tx_t *);
void backend_tx_rollback(backend_tx_t *);
#ifdef __cplusplus
}
#endif
#endif /* _CONFIGD_H */