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