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/*
23 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_CONFIGD_H
28#define	_CONFIGD_H
29
30#include <bsm/adt.h>
31#include <door.h>
32#include <pthread.h>
33#include <synch.h>
34#include <string.h>
35#include <sys/types.h>
36
37#include <libscf.h>
38#include <repcache_protocol.h>
39#include <libuutil.h>
40
41#include <configd_exit.h>
42
43#ifdef	__cplusplus
44extern "C" {
45#endif
46
47/*
48 * Lock order:
49 *
50 *	client lock
51 *		iter locks, in ID order
52 *		entity locks, in ID order
53 *
54 *		(any iter/entity locks)
55 *			backend locks (NORMAL, then NONPERSIST)
56 *				rc_node lock
57 *					children's rc_node lock
58 *				cache bucket lock
59 *					rc_node lock[*]
60 *
61 *	* only one node may be grabbed while holding a bucket lock
62 *
63 *	leaf locks:  (no other locks may be aquired while holding one)
64 *		rc_pg_notify_lock
65 *		rc_annotate_lock
66 */
67
68/*
69 * Returns the minimum size for a structure of type 't' such
70 * that it is safe to access field 'f'.
71 */
72#define	offsetofend(t, f)	(offsetof(t, f) + sizeof (((t *)0)->f))
73
74/*
75 * We want MUTEX_HELD, but we also want pthreads.  So we're stuck with this
76 * for the native build, at least until the build machines can catch up
77 * with the latest version of MUTEX_HELD() in <synch.h>.
78 */
79#if defined(NATIVE_BUILD)
80#undef	MUTEX_HELD
81#define	MUTEX_HELD(m)		_mutex_held((mutex_t *)(m))
82#endif
83
84/*
85 * Maximum levels of composition.
86 */
87#define	COMPOSITION_DEPTH	2
88
89#define	CONFIGD_CORE	"core.%f.%t.%p"
90
91#ifndef NDEBUG
92#define	bad_error(f, e)							\
93	uu_warn("%s:%d: %s() returned bad error %d.  Aborting.\n",	\
94	    __FILE__, __LINE__, f, e);					\
95	abort()
96#else
97#define	bad_error(f, e)		abort()
98#endif
99
100typedef enum backend_type {
101	BACKEND_TYPE_NORMAL		= 0,
102	BACKEND_TYPE_NONPERSIST,
103	BACKEND_TYPE_TOTAL			/* backend use only */
104} backend_type_t;
105
106/*
107 * pre-declare rc_* types
108 */
109typedef struct rc_node rc_node_t;
110typedef struct rc_snapshot rc_snapshot_t;
111typedef struct rc_snaplevel rc_snaplevel_t;
112
113/*
114 * notification layer -- protected by rc_pg_notify_lock
115 */
116typedef struct rc_notify_info rc_notify_info_t;
117typedef struct rc_notify_delete rc_notify_delete_t;
118
119#define	RC_NOTIFY_MAX_NAMES	4	/* enough for now */
120
121typedef struct rc_notify {
122	uu_list_node_t	rcn_list_node;
123	rc_node_t	*rcn_node;
124	rc_notify_info_t *rcn_info;
125	rc_notify_delete_t *rcn_delete;
126} rc_notify_t;
127
128struct rc_notify_delete {
129	rc_notify_t rnd_notify;
130	char rnd_fmri[REP_PROTOCOL_FMRI_LEN];
131};
132
133struct rc_notify_info {
134	uu_list_node_t	rni_list_node;
135	rc_notify_t	rni_notify;
136	const char	*rni_namelist[RC_NOTIFY_MAX_NAMES];
137	const char	*rni_typelist[RC_NOTIFY_MAX_NAMES];
138
139	int		rni_flags;
140	int		rni_waiters;
141	pthread_cond_t	rni_cv;
142};
143#define	RC_NOTIFY_ACTIVE	0x00000001
144#define	RC_NOTIFY_DRAIN		0x00000002
145#define	RC_NOTIFY_EMPTYING	0x00000004
146
147typedef struct rc_node_pg_notify {
148	uu_list_node_t	rnpn_node;
149	int		rnpn_fd;
150	rc_node_t	*rnpn_pg;
151} rc_node_pg_notify_t;
152
153/*
154 * cache layer
155 */
156
157/*
158 * The 'key' for the main object hash.  main_id is the main object
159 * identifier.  The rl_ids array contains:
160 *
161 *	TYPE		RL_IDS
162 *	scope		unused
163 *	service		unused
164 *	instance	{service_id}
165 *	snapshot	{service_id, instance_id}
166 *	snaplevel	{service_id, instance_id, name_id, snapshot_id}
167 *	propertygroup	{service_id, (instance_id or 0), (name_id or 0),
168 *			    (snapshot_id or 0), (l_id or 0)}
169 *	property	{service_id, (instance_id or 0), (name_id or 0),
170 *			    (snapshot_id or 0), (l_id or 0), pg_id, gen_id}
171 */
172#define	ID_SERVICE	0
173#define	ID_INSTANCE	1
174#define	ID_NAME		2
175#define	ID_SNAPSHOT	3
176#define	ID_LEVEL	4
177#define	ID_PG		5
178#define	ID_GEN		6
179#define	MAX_IDS	7
180typedef struct rc_node_lookup {
181	uint16_t	rl_type;		/* REP_PROTOCOL_ENTITY_* */
182	uint16_t	rl_backend;		/* BACKEND_TYPE_* */
183	uint32_t	rl_main_id;		/* primary identifier */
184	uint32_t	rl_ids[MAX_IDS];	/* context */
185} rc_node_lookup_t;
186
187struct rc_node {
188	/*
189	 * read-only data
190	 */
191	rc_node_lookup_t rn_id;			/* must be first */
192	uint32_t	rn_hash;
193	const char	*rn_name;
194
195	/*
196	 * type-specific state
197	 * (if space becomes an issue, these can become a union)
198	 */
199
200	/*
201	 * Used by instances, snapshots, and "composed property groups" only.
202	 * These are the entities whose properties should appear composed when
203	 * this entity is traversed by a composed iterator.  0 is the top-most
204	 * entity, down to COMPOSITION_DEPTH - 1.
205	 */
206	rc_node_t	*rn_cchain[COMPOSITION_DEPTH];
207
208	/*
209	 * used by property groups only
210	 */
211	const char	*rn_type;
212	uint32_t	rn_pgflags;
213	uint32_t	rn_gen_id;
214	uu_list_t	*rn_pg_notify_list;	/* prot by rc_pg_notify_lock */
215	rc_notify_t	rn_notify;		/* prot by rc_pg_notify_lock */
216
217	/*
218	 * used by properties only
219	 */
220	rep_protocol_value_type_t rn_valtype;
221	const char	*rn_values;		/* protected by rn_lock */
222	size_t		rn_values_count;	/* protected by rn_lock */
223	size_t		rn_values_size;		/* protected by rn_lock */
224
225	/*
226	 * used by snapshots only
227	 */
228	uint32_t	rn_snapshot_id;
229	rc_snapshot_t	*rn_snapshot;		/* protected by rn_lock */
230
231	/*
232	 * used by snaplevels only
233	 */
234	rc_snaplevel_t	*rn_snaplevel;
235
236	/*
237	 * mutable state
238	 */
239	pthread_mutex_t	rn_lock;
240	pthread_cond_t	rn_cv;
241	uint32_t	rn_flags;
242	uint32_t	rn_refs;		/* client reference count */
243	uint32_t	rn_erefs;		/* ephemeral ref count */
244	uint32_t	rn_other_refs;		/* atomic refcount */
245	uint32_t	rn_other_refs_held;	/* for 1->0 transitions */
246
247	uu_list_t	*rn_children;
248	uu_list_node_t	rn_sibling_node;
249
250	rc_node_t	*rn_parent;		/* set if on child list */
251	rc_node_t	*rn_former;		/* next former node */
252	rc_node_t	*rn_parent_ref;		/* reference count target */
253	const char	*rn_fmri;
254
255	/*
256	 * external state (protected by hash chain lock)
257	 */
258	rc_node_t	*rn_hash_next;
259};
260
261/*
262 * flag ordering:
263 *	RC_DYING
264 *		RC_NODE_CHILDREN_CHANGING
265 *		RC_NODE_CREATING_CHILD
266 *		RC_NODE_USING_PARENT
267 *			RC_NODE_IN_TX
268 *
269 * RC_NODE_USING_PARENT is special, because it lets you proceed up the tree,
270 * in the reverse of the usual locking order.  Because of this, there are
271 * limitations on what you can do while holding it.  While holding
272 * RC_NODE_USING_PARENT, you may:
273 *	bump or release your parent's reference count
274 *	access fields in your parent
275 *	hold RC_NODE_USING_PARENT in the parent, proceeding recursively.
276 *
277 * If you are only holding *one* node's RC_NODE_USING_PARENT, and:
278 *	you are *not* proceeding recursively, you can hold your
279 *	    immediate parent's RC_NODE_CHILDREN_CHANGING flag.
280 *	you hold your parent's RC_NODE_CHILDREN_CHANGING flag, you can add
281 *	    RC_NODE_IN_TX to your flags.
282 *	you want to grab a flag in your parent, you must lock your parent,
283 *	    lock yourself, drop RC_NODE_USING_PARENT, unlock yourself,
284 *	    then proceed to manipulate the parent.
285 */
286#define	RC_NODE_CHILDREN_CHANGING	0x00000001 /* child list in flux */
287#define	RC_NODE_HAS_CHILDREN		0x00000002 /* child list is accurate */
288
289#define	RC_NODE_IN_PARENT		0x00000004 /* I'm in my parent's list */
290#define	RC_NODE_USING_PARENT		0x00000008 /* parent ptr in use */
291#define	RC_NODE_CREATING_CHILD		0x00000010 /* a create is in progress */
292#define	RC_NODE_IN_TX			0x00000020 /* a tx is in progess */
293
294#define	RC_NODE_OLD			0x00000400 /* out-of-date object */
295#define	RC_NODE_ON_FORMER		0x00000800 /* on an rn_former list */
296
297#define	RC_NODE_PARENT_REF		0x00001000 /* parent_ref in use */
298#define	RC_NODE_UNREFED			0x00002000 /* unref processing active */
299#define	RC_NODE_DYING			0x00004000 /* node is being deleted */
300#define	RC_NODE_DEAD			0x00008000 /* node has been deleted */
301
302/*
303 * RC_NODE_DEAD means that the node no longer represents data in the
304 * backend, and we should return _DELETED errors to clients who try to use
305 * it.  Very much like a zombie process.
306 *
307 * RC_NODE_OLD also means that the node no longer represents data in the
308 * backend, but it's ok for clients to access it because we've loaded all of
309 * the children.  (This only happens for transactional objects such as
310 * property groups and snapshots, where we guarantee a stable view once
311 * a reference is obtained.)  When all client references are destroyed,
312 * however, the node should be destroyed.
313 *
314 * Though RC_NODE_DEAD is set by the rc_node_delete() code, it is also set
315 * by rc_node_no_client_refs() for RC_NODE_OLD nodes not long before
316 * they're destroyed.
317 */
318
319#define	RC_NODE_DYING_FLAGS						\
320	(RC_NODE_CHILDREN_CHANGING | RC_NODE_IN_TX | RC_NODE_DYING |	\
321	    RC_NODE_CREATING_CHILD)
322
323#define	RC_NODE_WAITING_FLAGS						\
324	(RC_NODE_DYING_FLAGS | RC_NODE_USING_PARENT)
325
326
327#define	NODE_LOCK(n)	(void) pthread_mutex_lock(&(n)->rn_lock)
328#define	NODE_UNLOCK(n)	(void) pthread_mutex_unlock(&(n)->rn_lock)
329
330
331typedef enum rc_auth_state {
332	RC_AUTH_UNKNOWN = 0,		/* No checks done yet. */
333	RC_AUTH_FAILED,			/* Authorization checked & failed. */
334	RC_AUTH_PASSED			/* Authorization succeeded. */
335} rc_auth_state_t;
336
337/*
338 * Some authorization checks are performed in rc_node_setup_tx() in
339 * response to the REP_PROTOCOL_PROPERTYGRP_TX_START message.  Other checks
340 * must wait until the actual transaction operations are received in the
341 * REP_PROTOCOL_PROPERTYGRP_TX_COMMIT message.  This second set of checks
342 * is performed in rc_tx_commit().  rnp_auth_string and rnp_authorized in
343 * the following structure are used to hold the results of the
344 * authorization checking done in rc_node_setup_tx() for later use by
345 * rc_tx_commit().
346 *
347 * In client.c transactions are represented by rc_node_ptr structures which
348 * point to a property group rc_node_t.  Thus, this is an appropriate place
349 * to hold authorization state.
350 */
351typedef struct rc_node_ptr {
352	rc_node_t	*rnp_node;
353	const char	*rnp_auth_string;	/* authorization string */
354	rc_auth_state_t	rnp_authorized;		/* transaction pre-auth rslt. */
355	char		rnp_deleted;		/* object was deleted */
356} rc_node_ptr_t;
357
358#define	NODE_PTR_NOT_HELD(npp) \
359	    ((npp)->rnp_node == NULL || !MUTEX_HELD(&(npp)->rnp_node->rn_lock))
360
361typedef int rc_iter_filter_func(rc_node_t *, void *);
362
363typedef struct rc_node_iter {
364	rc_node_t	*rni_parent;
365	int		rni_clevel;	/* index into rni_parent->rn_cchain[] */
366	rc_node_t	*rni_iter_node;
367	uu_list_walk_t	*rni_iter;
368	uint32_t	rni_type;
369
370	/*
371	 * for normal walks
372	 */
373	rc_iter_filter_func *rni_filter;
374	void		*rni_filter_arg;
375
376	/*
377	 * for value walks
378	 */
379	uint32_t	rni_offset;		/* next value offset */
380	uint32_t	rni_last_offset;	/* previous value offset */
381} rc_node_iter_t;
382
383typedef struct rc_node_tx {
384	rc_node_ptr_t	rnt_ptr;
385	int		rnt_authorized;		/* No need to check anymore. */
386} rc_node_tx_t;
387
388
389typedef struct cache_bucket {
390	pthread_mutex_t	cb_lock;
391	rc_node_t	*cb_head;
392
393	char		cb_pad[64 - sizeof (pthread_mutex_t) -
394			    2 * sizeof (rc_node_t *)];
395} cache_bucket_t;
396
397/*
398 * tx_commit_data_tx is an opaque structure which is defined in object.c.
399 * It contains the data of the transaction that is to be committed.
400 * Accessor functions in object.c allow other modules to retrieve
401 * information.
402 */
403typedef struct tx_commit_data tx_commit_data_t;
404
405/*
406 * Snapshots
407 */
408struct rc_snapshot {
409	uint32_t	rs_snap_id;
410
411	pthread_mutex_t	rs_lock;
412	pthread_cond_t	rs_cv;
413
414	uint32_t	rs_flags;
415	uint32_t	rs_refcnt;	/* references from rc_nodes */
416	uint32_t	rs_childref;	/* references to children */
417
418	rc_snaplevel_t	*rs_levels;	/* list of levels */
419	rc_snapshot_t	*rs_hash_next;
420};
421#define	RC_SNAPSHOT_FILLING	0x00000001	/* rs_levels changing */
422#define	RC_SNAPSHOT_READY	0x00000002
423#define	RC_SNAPSHOT_DEAD	0x00000004	/* no resources */
424
425typedef struct rc_snaplevel_pgs {
426	uint32_t	rsp_pg_id;
427	uint32_t	rsp_gen_id;
428} rc_snaplevel_pgs_t;
429
430struct rc_snaplevel {
431	rc_snapshot_t	*rsl_parent;
432	uint32_t	rsl_level_num;
433	uint32_t	rsl_level_id;
434
435	uint32_t	rsl_service_id;
436	uint32_t	rsl_instance_id;
437
438	const char	*rsl_scope;
439	const char	*rsl_service;
440	const char	*rsl_instance;
441
442	rc_snaplevel_t	*rsl_next;
443};
444
445/*
446 * Client layer -- the IDs fields must be first, in order for the search
447 * routines to work correctly.
448 */
449enum repcache_txstate {
450	REPCACHE_TX_INIT,
451	REPCACHE_TX_SETUP,
452	REPCACHE_TX_COMMITTED
453};
454
455typedef struct repcache_entity {
456	uint32_t	re_id;
457	uu_avl_node_t	re_link;
458	uint32_t	re_changeid;
459
460	pthread_mutex_t	re_lock;
461	uint32_t	re_type;
462	rc_node_ptr_t	re_node;
463	enum repcache_txstate re_txstate;	/* property groups only */
464} repcache_entity_t;
465
466typedef struct repcache_iter {
467	uint32_t	ri_id;
468	uu_avl_node_t	ri_link;
469
470	uint32_t	ri_type;	/* result type */
471
472	pthread_mutex_t	ri_lock;
473	uint32_t	ri_sequence;
474	rc_node_iter_t	*ri_iter;
475} repcache_iter_t;
476
477typedef struct repcache_client {
478	/*
479	 * constants
480	 */
481	uint32_t	rc_id;		/* must be first */
482	int		rc_all_auths;	/* bypass auth checks */
483	uint32_t	rc_debug;	/* debug flags */
484	pid_t		rc_pid;		/* pid of opening process */
485	door_id_t	rc_doorid;	/* a globally unique identifier */
486	int		rc_doorfd;	/* our door's FD */
487
488	/*
489	 * Constants used for security auditing
490	 *
491	 * rc_adt_session points to the audit session data that is used for
492	 * the life of the client.  rc_adt_sessionid is the session ID that
493	 * is initially assigned when the audit session is started.  See
494	 * start_audit_session() in client.c.  This session id is used for
495	 * audit events except when we are processing a set of annotated
496	 * events.  Annotated events use a separate session id so that they
497	 * can be grouped.  See set_annotation() in client.c.
498	 */
499	adt_session_data_t *rc_adt_session;	/* Session data. */
500	au_asid_t	rc_adt_sessionid;	/* Main session ID for */
501						/* auditing */
502
503	/*
504	 * client list linkage, protected by hash chain lock
505	 */
506	uu_list_node_t	rc_link;
507
508	/*
509	 * notification information, protected by rc_node layer
510	 */
511	rc_node_pg_notify_t	rc_pg_notify;
512	rc_notify_info_t	rc_notify_info;
513
514	/*
515	 * client_wait output, only usable by rc_notify_thr
516	 */
517	rc_node_ptr_t	rc_notify_ptr;
518
519	/*
520	 * register sets, protected by rc_lock
521	 */
522	uu_avl_t	*rc_entities;
523	uu_avl_t	*rc_iters;
524
525	/*
526	 * Variables, protected by rc_lock
527	 */
528	int		rc_refcnt;	/* in-progress door calls */
529	int		rc_flags;	/* see RC_CLIENT_* symbols below */
530	uint32_t	rc_changeid;	/* used to make backups idempotent */
531	pthread_t	rc_insert_thr;	/* single thread trying to insert */
532	pthread_t	rc_notify_thr;	/* single thread waiting for notify */
533	pthread_cond_t	rc_cv;
534	pthread_mutex_t	rc_lock;
535
536	/*
537	 * Per-client audit information.  These fields must be protected by
538	 * rc_annotate_lock separately from rc_lock because they may need
539	 * to be accessed from rc_node.c with an entity or iterator lock
540	 * held, and those must be taken after rc_lock.
541	 */
542	int		rc_annotate;	/* generate annotation event if set */
543	const char	*rc_operation;	/* operation for audit annotation */
544	const char	*rc_file;	/* file name for audit annotation */
545	pthread_mutex_t	rc_annotate_lock;
546} repcache_client_t;
547
548/* Bit definitions for rc_flags. */
549#define	RC_CLIENT_DEAD			0x00000001
550
551typedef struct client_bucket {
552	pthread_mutex_t	cb_lock;
553	uu_list_t	*cb_list;
554	char ch_pad[64 - sizeof (pthread_mutex_t) - sizeof (uu_list_t *)];
555} client_bucket_t;
556
557enum rc_ptr_type {
558	RC_PTR_TYPE_ENTITY = 1,
559	RC_PTR_TYPE_ITER
560};
561
562typedef struct request_log_ptr {
563	enum rc_ptr_type	rlp_type;
564	uint32_t		rlp_id;
565	void			*rlp_ptr; /* repcache_{entity,iter}_t */
566	void			*rlp_data;	/* rc_node, for ENTITY only */
567} request_log_ptr_t;
568
569#define	MAX_PTRS	3
570
571/*
572 * rl_start through rl_client cannot move without changing start_log()
573 */
574typedef struct request_log_entry {
575	hrtime_t		rl_start;
576	hrtime_t		rl_end;
577	pthread_t		rl_tid;
578	uint32_t		rl_clientid;
579	repcache_client_t	*rl_client;
580	enum rep_protocol_requestid rl_request;
581	rep_protocol_responseid_t rl_response;
582	int			rl_num_ptrs;
583	request_log_ptr_t	rl_ptrs[MAX_PTRS];
584} request_log_entry_t;
585
586/*
587 * thread information
588 */
589typedef enum thread_state {
590	TI_CREATED,
591	TI_DOOR_RETURN,
592	TI_SIGNAL_WAIT,
593	TI_MAIN_DOOR_CALL,
594	TI_CLIENT_CALL
595} thread_state_t;
596
597typedef struct thread_info {
598	pthread_t	ti_thread;
599	uu_list_node_t	ti_node;		/* for list of all thread */
600
601	/*
602	 * per-thread globals
603	 */
604	ucred_t		*ti_ucred;		/* for credential lookups */
605	int		ti_ucred_read;		/* ucred holds current creds */
606
607	/*
608	 * per-thread state information, for debuggers
609	 */
610	hrtime_t	ti_lastchange;
611
612	thread_state_t	ti_state;
613	thread_state_t	ti_prev_state;
614
615	repcache_client_t *ti_active_client;
616	request_log_entry_t	ti_log;
617
618	struct rep_protocol_request *ti_client_request;
619	repository_door_request_t *ti_main_door_request;
620
621} thread_info_t;
622
623/*
624 * Backend layer
625 */
626typedef struct backend_query backend_query_t;
627typedef struct backend_tx backend_tx_t;
628
629/*
630 * configd.c
631 */
632int create_connection(ucred_t *cred, repository_door_request_t *rp,
633    size_t rp_size, int *out_fd);
634
635thread_info_t *thread_self(void);
636void thread_newstate(thread_info_t *, thread_state_t);
637ucred_t *get_ucred(void);
638int ucred_is_privileged(ucred_t *);
639
640adt_session_data_t *get_audit_session(void);
641
642void configd_critical(const char *, ...);
643void configd_vcritical(const char *, va_list);
644void configd_info(const char *, ...);
645
646extern int is_main_repository;
647extern int max_repository_backups;
648
649/*
650 * maindoor.c
651 */
652int setup_main_door(const char *);
653
654/*
655 * client.c
656 */
657int client_annotation_needed(char *, size_t, char *, size_t);
658void client_annotation_finished(void);
659int create_client(pid_t, uint32_t, int, int *);
660int client_init(void);
661int client_is_privileged(void);
662void log_enter(request_log_entry_t *);
663
664/*
665 * rc_node.c, backend/cache interfaces (rc_node_t)
666 */
667int rc_node_init();
668int rc_check_type_name(uint32_t, const char *);
669
670void rc_node_ptr_free_mem(rc_node_ptr_t *);
671void rc_node_rele(rc_node_t *);
672rc_node_t *rc_node_setup(rc_node_t *, rc_node_lookup_t *,
673    const char *, rc_node_t *);
674rc_node_t *rc_node_setup_pg(rc_node_t *, rc_node_lookup_t *, const char *,
675    const char *, uint32_t, uint32_t, rc_node_t *);
676rc_node_t *rc_node_setup_snapshot(rc_node_t *, rc_node_lookup_t *, const char *,
677    uint32_t, rc_node_t *);
678rc_node_t *rc_node_setup_snaplevel(rc_node_t *, rc_node_lookup_t *,
679    rc_snaplevel_t *, rc_node_t *);
680int rc_node_create_property(rc_node_t *, rc_node_lookup_t *,
681    const char *, rep_protocol_value_type_t, const char *, size_t, size_t);
682
683rc_node_t *rc_node_alloc(void);
684void rc_node_destroy(rc_node_t *);
685
686/*
687 * rc_node.c, client interface (rc_node_ptr_t, rc_node_iter_t)
688 */
689void rc_node_ptr_init(rc_node_ptr_t *);
690int rc_local_scope(uint32_t, rc_node_ptr_t *);
691
692void rc_node_clear(rc_node_ptr_t *, int);
693void rc_node_ptr_assign(rc_node_ptr_t *, const rc_node_ptr_t *);
694int rc_node_name(rc_node_ptr_t *, char *, size_t, uint32_t, size_t *);
695int rc_node_fmri(rc_node_ptr_t *, char *, size_t, size_t *);
696int rc_node_parent_type(rc_node_ptr_t *, uint32_t *);
697int rc_node_get_child(rc_node_ptr_t *, const char *, uint32_t, rc_node_ptr_t *);
698int rc_node_get_parent(rc_node_ptr_t *, uint32_t, rc_node_ptr_t *);
699int rc_node_get_property_type(rc_node_ptr_t *, rep_protocol_value_type_t *);
700int rc_node_get_property_value(rc_node_ptr_t *,
701    struct rep_protocol_value_response *, size_t *);
702int rc_node_create_child(rc_node_ptr_t *, uint32_t, const char *,
703    rc_node_ptr_t *);
704int rc_node_create_child_pg(rc_node_ptr_t *, uint32_t, const char *,
705    const char *, uint32_t, rc_node_ptr_t *);
706int rc_node_update(rc_node_ptr_t *);
707int rc_node_delete(rc_node_ptr_t *);
708int rc_node_next_snaplevel(rc_node_ptr_t *, rc_node_ptr_t *);
709
710int rc_node_setup_iter(rc_node_ptr_t *, rc_node_iter_t **, uint32_t,
711    size_t, const char *);
712
713int rc_iter_next(rc_node_iter_t *, rc_node_ptr_t *, uint32_t);
714int rc_iter_next_value(rc_node_iter_t *, struct rep_protocol_value_response *,
715    size_t *, int);
716void rc_iter_destroy(rc_node_iter_t **);
717
718int rc_node_setup_tx(rc_node_ptr_t *, rc_node_ptr_t *);
719int rc_tx_commit(rc_node_ptr_t *, const void *, size_t);
720
721void rc_pg_notify_init(rc_node_pg_notify_t *);
722int rc_pg_notify_setup(rc_node_pg_notify_t *, rc_node_ptr_t *, int);
723void rc_pg_notify_fini(rc_node_pg_notify_t *);
724
725void rc_notify_info_init(rc_notify_info_t *);
726int rc_notify_info_add_name(rc_notify_info_t *, const char *);
727int rc_notify_info_add_type(rc_notify_info_t *, const char *);
728int rc_notify_info_wait(rc_notify_info_t *, rc_node_ptr_t *, char *, size_t);
729void rc_notify_info_fini(rc_notify_info_t *);
730
731int rc_snapshot_take_new(rc_node_ptr_t *, const char *,
732    const char *, const char *, rc_node_ptr_t *);
733int rc_snapshot_take_attach(rc_node_ptr_t *, rc_node_ptr_t *);
734int rc_snapshot_attach(rc_node_ptr_t *, rc_node_ptr_t *);
735
736/*
737 * file_object.c
738 */
739int object_fill_children(rc_node_t *);
740int object_create(rc_node_t *, uint32_t, const char *, rc_node_t **);
741int object_create_pg(rc_node_t *, uint32_t, const char *, const char *,
742    uint32_t, rc_node_t **);
743
744int object_delete(rc_node_t *);
745void object_free_values(const char *, uint32_t, size_t, size_t);
746
747int object_fill_snapshot(rc_snapshot_t *);
748
749int object_snapshot_take_new(rc_node_t *, const char *, const char *,
750    const char *, rc_node_t **);
751int object_snapshot_attach(rc_node_lookup_t *, uint32_t *, int);
752
753/*
754 * object.c
755 */
756int object_tx_commit(rc_node_lookup_t *, tx_commit_data_t *, uint32_t *);
757
758/* Functions to access transaction commands. */
759int tx_cmd_action(tx_commit_data_t *, size_t,
760    enum rep_protocol_transaction_action *);
761size_t tx_cmd_count(tx_commit_data_t *);
762int tx_cmd_nvalues(tx_commit_data_t *, size_t, uint32_t *);
763int tx_cmd_prop(tx_commit_data_t *, size_t, const char **);
764int tx_cmd_prop_type(tx_commit_data_t *, size_t, uint32_t *);
765int tx_cmd_value(tx_commit_data_t *, size_t, uint32_t, const char **);
766void tx_commit_data_free(tx_commit_data_t *);
767int tx_commit_data_new(const void *, size_t, tx_commit_data_t **);
768
769/*
770 * snapshot.c
771 */
772int rc_snapshot_get(uint32_t, rc_snapshot_t **);
773void rc_snapshot_rele(rc_snapshot_t *);
774void rc_snaplevel_hold(rc_snaplevel_t *);
775void rc_snaplevel_rele(rc_snaplevel_t *);
776
777/*
778 * backend.c
779 */
780int backend_init(const char *, const char *, int);
781boolean_t backend_is_upgraded(backend_tx_t *);
782void backend_fini(void);
783
784rep_protocol_responseid_t backend_create_backup(const char *);
785rep_protocol_responseid_t backend_switch(int);
786
787/*
788 * call on any database inconsistency -- cleans up state as best it can,
789 * and exits with a "Database Bad" error code.
790 */
791void backend_panic(const char *, ...) __NORETURN;
792#pragma rarely_called(backend_panic)
793
794backend_query_t *backend_query_alloc(void);
795void backend_query_append(backend_query_t *, const char *);
796void backend_query_add(backend_query_t *, const char *, ...);
797void backend_query_free(backend_query_t *);
798
799typedef int backend_run_callback_f(void *data, int columns, char **vals,
800    char **names);
801#define	BACKEND_CALLBACK_CONTINUE	0
802#define	BACKEND_CALLBACK_ABORT		1
803
804backend_run_callback_f backend_fail_if_seen;	/* aborts TX if called */
805
806int backend_run(backend_type_t, backend_query_t *,
807    backend_run_callback_f *, void *);
808
809int backend_tx_begin(backend_type_t, backend_tx_t **);
810int backend_tx_begin_ro(backend_type_t, backend_tx_t **);
811void backend_tx_end_ro(backend_tx_t *);
812
813enum id_space {
814	BACKEND_ID_SERVICE_INSTANCE,
815	BACKEND_ID_PROPERTYGRP,
816	BACKEND_ID_GENERATION,
817	BACKEND_ID_PROPERTY,
818	BACKEND_ID_VALUE,
819	BACKEND_ID_SNAPNAME,
820	BACKEND_ID_SNAPSHOT,
821	BACKEND_ID_SNAPLEVEL,
822	BACKEND_ID_INVALID	/* always illegal */
823};
824
825uint32_t backend_new_id(backend_tx_t *, enum id_space);
826int backend_tx_run_update(backend_tx_t *, const char *, ...);
827int backend_tx_run_update_changed(backend_tx_t *, const char *, ...);
828int backend_tx_run_single_int(backend_tx_t *tx, backend_query_t *q,
829    uint32_t *buf);
830int backend_tx_run(backend_tx_t *, backend_query_t *,
831    backend_run_callback_f *, void *);
832
833int backend_tx_commit(backend_tx_t *);
834void backend_tx_rollback(backend_tx_t *);
835
836#ifdef	__cplusplus
837}
838#endif
839
840#endif	/* _CONFIGD_H */
841