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