xref: /titanic_52/usr/src/cmd/svc/configd/configd.h (revision b09b8ac7cd4799ad423c03bc4408dfadc2237f25)
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 /*
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 
103 typedef 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  */
112 typedef struct rc_node rc_node_t;
113 typedef struct rc_snapshot rc_snapshot_t;
114 typedef struct rc_snaplevel rc_snaplevel_t;
115 
116 /*
117  * notification layer -- protected by rc_pg_notify_lock
118  */
119 typedef struct rc_notify_info rc_notify_info_t;
120 typedef struct rc_notify_delete rc_notify_delete_t;
121 
122 #define	RC_NOTIFY_MAX_NAMES	4	/* enough for now */
123 
124 typedef 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 
131 struct rc_notify_delete {
132 	rc_notify_t rnd_notify;
133 	char rnd_fmri[REP_PROTOCOL_FMRI_LEN];
134 };
135 
136 struct 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 
150 typedef 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
183 typedef 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 
190 struct 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 
312 typedef 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  */
332 typedef 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 
342 typedef int rc_iter_filter_func(rc_node_t *, void *);
343 
344 typedef 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 
364 typedef 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 
370 typedef 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  */
384 typedef struct tx_commit_data tx_commit_data_t;
385 
386 /*
387  * Snapshots
388  */
389 struct 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 
406 typedef struct rc_snaplevel_pgs {
407 	uint32_t	rsp_pg_id;
408 	uint32_t	rsp_gen_id;
409 } rc_snaplevel_pgs_t;
410 
411 struct 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  */
430 enum repcache_txstate {
431 	REPCACHE_TX_INIT,
432 	REPCACHE_TX_SETUP,
433 	REPCACHE_TX_COMMITTED
434 };
435 
436 typedef 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 
447 typedef 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 
458 typedef 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 
532 typedef 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 
538 enum rc_ptr_type {
539 	RC_PTR_TYPE_ENTITY = 1,
540 	RC_PTR_TYPE_ITER
541 };
542 
543 typedef 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  */
555 typedef 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  */
570 typedef 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 
578 typedef 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  */
607 typedef struct backend_query backend_query_t;
608 typedef struct backend_tx backend_tx_t;
609 
610 /*
611  * configd.c
612  */
613 int create_connection(ucred_t *cred, repository_door_request_t *rp,
614     size_t rp_size, int *out_fd);
615 
616 thread_info_t *thread_self(void);
617 void thread_newstate(thread_info_t *, thread_state_t);
618 ucred_t *get_ucred(void);
619 int ucred_is_privileged(ucred_t *);
620 
621 adt_session_data_t *get_audit_session(void);
622 
623 void configd_critical(const char *, ...);
624 void configd_vcritical(const char *, va_list);
625 
626 extern int is_main_repository;
627 extern int max_repository_backups;
628 
629 /*
630  * maindoor.c
631  */
632 int setup_main_door(const char *);
633 
634 /*
635  * client.c
636  */
637 int client_annotation_needed(char *, size_t, char *, size_t);
638 void client_annotation_finished(void);
639 int create_client(pid_t, uint32_t, int, int *);
640 int client_init(void);
641 int client_is_privileged(void);
642 void log_enter(request_log_entry_t *);
643 
644 /*
645  * rc_node.c, backend/cache interfaces (rc_node_t)
646  */
647 int rc_node_init();
648 int rc_check_type_name(uint32_t, const char *);
649 
650 void rc_node_ptr_free_mem(rc_node_ptr_t *);
651 void rc_node_rele(rc_node_t *);
652 rc_node_t *rc_node_setup(rc_node_t *, rc_node_lookup_t *,
653     const char *, rc_node_t *);
654 rc_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 *);
656 rc_node_t *rc_node_setup_snapshot(rc_node_t *, rc_node_lookup_t *, const char *,
657     uint32_t, rc_node_t *);
658 rc_node_t *rc_node_setup_snaplevel(rc_node_t *, rc_node_lookup_t *,
659     rc_snaplevel_t *, rc_node_t *);
660 int 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 
663 rc_node_t *rc_node_alloc(void);
664 void rc_node_destroy(rc_node_t *);
665 
666 /*
667  * rc_node.c, client interface (rc_node_ptr_t, rc_node_iter_t)
668  */
669 void rc_node_ptr_init(rc_node_ptr_t *);
670 int rc_local_scope(uint32_t, rc_node_ptr_t *);
671 
672 void rc_node_clear(rc_node_ptr_t *, int);
673 void rc_node_ptr_assign(rc_node_ptr_t *, const rc_node_ptr_t *);
674 int rc_node_name(rc_node_ptr_t *, char *, size_t, uint32_t, size_t *);
675 int rc_node_fmri(rc_node_ptr_t *, char *, size_t, size_t *);
676 int rc_node_parent_type(rc_node_ptr_t *, uint32_t *);
677 int rc_node_get_child(rc_node_ptr_t *, const char *, uint32_t, rc_node_ptr_t *);
678 int rc_node_get_parent(rc_node_ptr_t *, uint32_t, rc_node_ptr_t *);
679 int rc_node_get_property_type(rc_node_ptr_t *, rep_protocol_value_type_t *);
680 int rc_node_get_property_value(rc_node_ptr_t *,
681     struct rep_protocol_value_response *, size_t *);
682 int rc_node_create_child(rc_node_ptr_t *, uint32_t, const char *,
683     rc_node_ptr_t *);
684 int rc_node_create_child_pg(rc_node_ptr_t *, uint32_t, const char *,
685     const char *, uint32_t, rc_node_ptr_t *);
686 int rc_node_update(rc_node_ptr_t *);
687 int rc_node_delete(rc_node_ptr_t *);
688 int rc_node_next_snaplevel(rc_node_ptr_t *, rc_node_ptr_t *);
689 
690 int rc_node_setup_iter(rc_node_ptr_t *, rc_node_iter_t **, uint32_t,
691     size_t, const char *);
692 
693 int rc_iter_next(rc_node_iter_t *, rc_node_ptr_t *, uint32_t);
694 int rc_iter_next_value(rc_node_iter_t *, struct rep_protocol_value_response *,
695     size_t *, int);
696 void rc_iter_destroy(rc_node_iter_t **);
697 
698 int rc_node_setup_tx(rc_node_ptr_t *, rc_node_ptr_t *);
699 int rc_tx_commit(rc_node_ptr_t *, const void *, size_t);
700 
701 void rc_pg_notify_init(rc_node_pg_notify_t *);
702 int rc_pg_notify_setup(rc_node_pg_notify_t *, rc_node_ptr_t *, int);
703 void rc_pg_notify_fini(rc_node_pg_notify_t *);
704 
705 void rc_notify_info_init(rc_notify_info_t *);
706 int rc_notify_info_add_name(rc_notify_info_t *, const char *);
707 int rc_notify_info_add_type(rc_notify_info_t *, const char *);
708 int rc_notify_info_wait(rc_notify_info_t *, rc_node_ptr_t *, char *, size_t);
709 void rc_notify_info_fini(rc_notify_info_t *);
710 
711 int rc_snapshot_take_new(rc_node_ptr_t *, const char *,
712     const char *, const char *, rc_node_ptr_t *);
713 int rc_snapshot_take_attach(rc_node_ptr_t *, rc_node_ptr_t *);
714 int rc_snapshot_attach(rc_node_ptr_t *, rc_node_ptr_t *);
715 
716 /*
717  * file_object.c
718  */
719 int object_fill_children(rc_node_t *);
720 int object_create(rc_node_t *, uint32_t, const char *, rc_node_t **);
721 int object_create_pg(rc_node_t *, uint32_t, const char *, const char *,
722     uint32_t, rc_node_t **);
723 
724 int object_delete(rc_node_t *);
725 void object_free_values(const char *, uint32_t, size_t, size_t);
726 
727 int object_fill_snapshot(rc_snapshot_t *);
728 
729 int object_snapshot_take_new(rc_node_t *, const char *, const char *,
730     const char *, rc_node_t **);
731 int object_snapshot_attach(rc_node_lookup_t *, uint32_t *, int);
732 
733 /*
734  * object.c
735  */
736 int object_tx_commit(rc_node_lookup_t *, tx_commit_data_t *, uint32_t *);
737 
738 /* Functions to access transaction commands. */
739 int tx_cmd_action(tx_commit_data_t *, size_t,
740     enum rep_protocol_transaction_action *);
741 size_t tx_cmd_count(tx_commit_data_t *);
742 int tx_cmd_nvalues(tx_commit_data_t *, size_t, uint32_t *);
743 int tx_cmd_prop(tx_commit_data_t *, size_t, const char **);
744 int tx_cmd_prop_type(tx_commit_data_t *, size_t, uint32_t *);
745 int tx_cmd_value(tx_commit_data_t *, size_t, uint32_t, const char **);
746 void tx_commit_data_free(tx_commit_data_t *);
747 int tx_commit_data_new(const void *, size_t, tx_commit_data_t **);
748 
749 /*
750  * snapshot.c
751  */
752 int rc_snapshot_get(uint32_t, rc_snapshot_t **);
753 void rc_snapshot_rele(rc_snapshot_t *);
754 void rc_snaplevel_hold(rc_snaplevel_t *);
755 void rc_snaplevel_rele(rc_snaplevel_t *);
756 
757 /*
758  * backend.c
759  */
760 int backend_init(const char *, const char *, int);
761 void backend_fini(void);
762 
763 rep_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  */
769 void backend_panic(const char *, ...) __NORETURN;
770 #pragma rarely_called(backend_panic)
771 
772 backend_query_t *backend_query_alloc(void);
773 void backend_query_append(backend_query_t *, const char *);
774 void backend_query_add(backend_query_t *, const char *, ...);
775 void backend_query_free(backend_query_t *);
776 
777 typedef 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 
782 backend_run_callback_f backend_fail_if_seen;	/* aborts TX if called */
783 
784 int backend_run(backend_type_t, backend_query_t *,
785     backend_run_callback_f *, void *);
786 
787 int backend_tx_begin(backend_type_t, backend_tx_t **);
788 int backend_tx_begin_ro(backend_type_t, backend_tx_t **);
789 void backend_tx_end_ro(backend_tx_t *);
790 
791 enum 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 
803 uint32_t backend_new_id(backend_tx_t *, enum id_space);
804 int backend_tx_run_update(backend_tx_t *, const char *, ...);
805 int backend_tx_run_update_changed(backend_tx_t *, const char *, ...);
806 int backend_tx_run_single_int(backend_tx_t *tx, backend_query_t *q,
807     uint32_t *buf);
808 int backend_tx_run(backend_tx_t *, backend_query_t *,
809     backend_run_callback_f *, void *);
810 
811 int backend_tx_commit(backend_tx_t *);
812 void backend_tx_rollback(backend_tx_t *);
813 
814 #ifdef	__cplusplus
815 }
816 #endif
817 
818 #endif	/* _CONFIGD_H */
819