repcache_protocol.h revision 5040:ff6ebd8761a6
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 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_REPCACHE_PROTOCOL_H
28#define	_REPCACHE_PROTOCOL_H
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32/*
33 * The Repository Cache Protocol
34 * -----------------------------
35 *
36 * 1. Introduction
37 * ---------------
38 * This header file defines the private protocols between libscf(3lib) and
39 * svc.configd(1m).  There are two separate protocols:
40 *
41 * 1.	The 'global' protocol, accessible via an fattach(3C)ed door located
42 *	at REPOSITORY_DOOR_NAME.
43 *
44 * 2.	The 'client' protocol, accessible through a door created using the
45 *	global protocol, which allows access to the repository.
46 *
47 * 1.1 Design restrictions
48 * -----------------------
49 * A basic constraint of the door IPC mechanism is that there is no reliable
50 * delivery.  In particular:
51 *
52 * 1.	If libscf(3lib) recieves an EINTR from door_call(), it doesn't know
53 *      whether or not the server recieved (and is processing) its request.
54 *
55 * 2.	When svc.configd(1M) calls door_return(), the client may have already
56 *	received an EINTR, aborting its door_call().  In this case, the
57 *	returned values are dropped on the floor.
58 *
59 * The practical upshot of all of this is simple:
60 *
61 *	Every individual protocol action must be idempotent.
62 *
63 * That is, a client must be able to retry any single request multiple times,
64 * and get the correct results.
65 *
66 * 1.2. Protocol shorthand
67 * -----------------------
68 * We represent by "REQUEST(arg1, arg2) -> result, res1, [desc]" a request code
69 * of REP_PROTOCOL_REQUEST (or REPOSITORY_DOOR_REQUEST), which takes two
70 * additional arguments, arg1 and arg2, and returns a result code, res1, and
71 * a file descriptor desc.
72 *
73 * If an error occurs, the server will usually only send the result code. (a
74 * short return)
75 *
76 * Inside the protocol destription, <foo> indicates the type foo indicates.
77 *
78 * 2. The Global protocol
79 * ----------------------
80 * Everything starting with "REPOSITORY_DOOR" or "repository_door" belongs
81 * to the global protocol.
82 *
83 * 2.1. Global requests
84 * --------------------
85 *
86 * REQUEST_CONNECT(rdr_flags, ...) -> result, [new_door]
87 *	Request a new Client door.  rdr_flags determines attributes of the
88 *	connection:
89 *
90 *	    FLAG_DEBUG
91 *		Sets connection debugging flags to those in rdr_debug.
92 *
93 *	The new door is returned with DOOR_RELEASE set, so if the client does
94 *	not recieve the response, the new door will recieve an unref
95 *	notification.  This makes this request idempotent.
96 *
97 * 2.2. Global reponse codes
98 * -------------------------
99 * GLXXX: This needs to be thought through.
100 *
101 * SUCCESS
102 * FAIL_BAD_REQUEST
103 * FAIL_VERSION_MISMATCH
104 * FAIL_BAD_FLAG
105 * FAIL_BAD_USER
106 * FAIL_NO_RESOURCES
107 *
108 * 3. The Client protocol
109 * ----------------------
110 * Everything starting with "REP_PROTOCOL" or "rep_protocol" belongs to the
111 * client protocol.
112 *
113 * 3.1. Techniques used
114 * --------------------
115 * 3.1.1. Client-controlled identifiers
116 *
117 * An idiom the protocol uses to lower the number of round trips is
118 * client-controlled identifiers.  The basic idea is this:  whenever a
119 * client wants to set up and use a piece of server state, he picks an
120 * integer *which he knows is not in use* to identify it.  The server then
121 * maintains per-client, per-resource id->resource maps.  This has a number
122 * of advantages:
123 *
124 * 1.	Since the client allocates the identifiers, we don't need to do
125 *	a round-trip just to allocate a number.
126 *
127 * 2.	Since it is the client's job to make sure identifiers don't collide,
128 *	idempotency for setup (destroy) are simple:  If the identifier
129 *	already exists (does not exist), we just return success.
130 *
131 * 3.	Since the identifiers are per-client, the design automatically
132 *	precludes clients being able to manipulate other client's state.
133 *
134 * 3.1.2 Sequence numbers
135 *
136 * A standard way of gaining idempotency is introducing sequence numbers.
137 * These are simply integers which get incremented at points in the protocol,
138 * and make sure the client and server are in sync.
139 *
140 * In this protocol, we use sequence numbers for requests (like ITER_READ)
141 * which are repeated, returning different data each time.  Since requests
142 * can also be repeated due to unreliable dispatch, the client increments
143 * the sequence number after every successful request.  This allows the server
144 * to differentiate the two cases. (note that this means that failing
145 * requests have no side effects and are repeatable)
146 *
147 * 3.2. Client abstractions
148 * ------------------------
149 * 3.2.1 Entities
150 *
151 * An "entity" is a typed register which the client can manipulate.
152 * Entities are named in the protocol by client-controlled identifiers.
153 * They have a fixed type for their entire lifetime, and may be in one
154 * of two states:
155 *
156 * valid
157 *	The entity has a valid value, and may be read from.  This state
158 *	is reached by a successful write to the entity by some protocol
159 *	step.
160 *
161 * invalid
162 *	The entity does not contain a valid value.  There are a number
163 *	of ways to reach this state:
164 *
165 *	1.  The entity was just created.
166 *	2.  The underlying object that this entity refers to was destroyed.
167 *	3.  A protocol request which would have modified this entity
168 *	    failed.
169 *
170 * An entity is an element in the tree of repository data.  Every entity
171 * (except for the most distant SCOPE) has exactly one parent.  Entities
172 * can have multiple children of different types, restricted by its base
173 * type.
174 *
175 * The ENTITY_GET call is used to get the root of the tree (the most local
176 * scope)
177 *
178 * 3.2.2. The entity tree
179 * ----------------------
180 * The structure of a scope is as follows:
181 *
182 *	 _______
183 *	| SCOPE |
184 *	|_______|
185 *	    \ .
186 *	     \ .
187 *	      \_________
188 *	      | SERVICE |
189 *	      |_________|
190 *		/.    \ .
191 *	       /.      \ .
192 *	  ____/		\__________
193 *	 | PG |		| INSTANCE |
194 *	 |____|		|__________|
195 *			  /.	 \ .
196 *			 /.	  \ .
197 *		    ____/	   \__________
198 *		   | PG |	   | SNAPSHOT |
199 *		   |____|	   |__________|
200 *					\ .
201 *					 \ .
202 *					  \___________
203 *					  | SNAPLEVEL |
204 *					  |___________|
205 *					     /.
206 *					    /.
207 *				       ____/
208 *				      | PG |
209 *				      |____|
210 *
211 * Where the dots indicate an arbitrary number (including 0) of children.
212 *
213 * For a given scope, the next scope (in the sense of distance) is its
214 * TYPE_SCOPE parent.  The furthest out scope has no parent.
215 *
216 * 3.2.2 Iterators
217 *
218 * GLXXX
219 *
220 * 3.3. Client requests
221 * --------------------
222 *
223 * CLOSE() -> result
224 *	Closes the connection, revoking the door.  After this call completes,
225 *	no further calls will succeed.
226 *
227 * ENTITY_SETUP(entity_id, type) -> result
228 *	Sets up an entity, identified by entity_id, to identify a single
229 *	<type>.  <type> may not be TYPE_NONE.
230 *
231 * ENTITY_NAME(entity_id, name_type) -> result, name
232 *	Returns the name of entity_id.  name_type determines which type of
233 *	name to get.
234 *
235 * ENTITY_PARENT_TYPE(entity_id) -> result, parent_type
236 *	Retrieves the type of entity_id's parent
237 *
238 * ENTITY_GET_CHILD(entity_id, child_id, name) -> result
239 *	Puts entity_id's child (of child_id's type) named 'name' into child_id.
240 *
241 * ENTITY_GET_PARENT(entity_id, out_id) -> result
242 *	Puts entity_id's parent into out_id.
243 *
244 * ENTITY_GET(entity_id, number) -> result
245 *	Makes entity_id point to a particular object.  If any error
246 *	occurs, dest_id will be invalid.
247 *
248 * ENTITY_UPDATE(entity_id, changeid) -> result
249 *	Updates the entity to pick up any new changes.
250 *
251 * ENTITY_CREATE_CHILD(entity_id, type, name, child_id, changeid) -> result
252 *	Attaches the object of type /type/ in child_id as the child of
253 *	entity_id named 'name'.
254 *
255 * ENTITY_CREATE_PG(entity_id, name, type, flags, child_id, changeid) -> result
256 *	Creates a property group child of entity_id named 'name', type 'type'
257 *	and flags 'flags', and puts the resulting object in child_id.
258 *
259 * ENTITY_DELETE(entity_id, changeid) -> result
260 *	Deletes the entity represented by entity_id.
261 *
262 * ENTITY_RESET(entity_id) -> result
263 *	Resets the entity.
264 *
265 * ENTITY_TEARDOWN(entity_id) -> result
266 *	Destroys the entity entity_id.
267 *
268 * ITER_SETUP(iter_id) -> result
269 *	Sets up an iterator id.
270 *
271 * ITER_START(iter_id, entity_id, itertype, flags, pattern) -> result
272 *	Sets up an iterator, identified by iter_id, which will iterate the
273 *	<itertype> children of entity_id whose names match 'pattern',
274 *	with the matching controlled by flags.  Initializing an iterator
275 *	counts as the first sequence number (1).
276 *
277 * ITER_READ(iter_id, sequence, entity_id) -> result
278 *	Retrieves the next element of iterator iter_id.  Sequence starts at 2,
279 *	and is incremented by the client after each successful iteration.
280 *	The result is written to entity_id, which must be of the same type
281 *	as the iterator result.  The iterator must not be iterating values.
282 *
283 * ITER_READ_VALUE(iter_id, sequence) -> result, type, value
284 *	Retrieves the next value for iterator iter_id.  Sequence starts at 2,
285 *	and is incremented by the client after each successful iteration.
286 *	The iterator must be iterating a property's values.
287 *
288 * ITER_RESET(iter_id) -> result
289 *	Throws away any accumulated state.
290 *
291 * ITER_TEARDOWN(iter_id) -> result
292 *	Destroys the iterator iter_id.
293 *
294 * NEXT_SNAPLEVEL(entity_src, entity_dst) -> result
295 *	If entity_src is a snapshot, set entity_dst to the first snaplevel
296 *	in it.  If entity_src is a snaplevel, set entity_dst to the next
297 *	snaplevel, or fail if there isn't one.
298 *
299 * SNAPSHOT_TAKE(entity_id, name, dest_id, flags) -> result
300 *	Takes a snapshot of entity_id, creating snaplevels for the instance and
301 *	its parent service.  If flags is REP_SNAPSHOT_NEW, a new snapshot named
302 *	'name' is created as a child of entity_id, dest_id is pointed to it,
303 *	and the new snaplevels are attached to it.  If flags is
304 *	REP_SNAPSHOT_ATTACH, name must be empty, and the new snaplevels are
305 *	attached to the snapshot dest_id points to.
306 *
307 * SNAPSHOT_TAKE_NAMED(entity_id, instname, svcname, name, dest_id) -> result
308 *	Like SNAPSHOT_TAKE, but always acts as if REP_SNAPSHOT_NEW is
309 *	specified, and instname and svcname override the actual service and
310 *	instance names, respectively, written into the snaplevels.
311 *
312 *	Note that this is only useful for writing snapshots which will later
313 *	be transferred to another instance (svc:/svcname:instname/)
314 *
315 * SNAPSHOT_ATTACH(source_id, dest_id) -> result
316 *	The snaplevels attached to the snapshot referenced by source_id are
317 *	attached to the snapshot dest_id is pointed at.
318 *
319 * PROPERTY_GET_TYPE(entity_id) -> result, value type
320 *	Finds the value type of entity_id, which must be a property.
321 *
322 * PROPERTY_GET_VALUE(entity_id) -> result, type, value
323 *	If the property contains a single value, returns it and its type.
324 *
325 * PROPERTYGRP_SETUP_WAIT(entity_id) -> result, [pipe fd]
326 *	Sets up a notification for changes to the object entity_id currently
327 *	references.  On success, returns one side of a pipe -- when there
328 *	has been a change (or the daemon dies), the other end of the pipe will
329 *	be closed.
330 *
331 *	Only one of these can be set up per client -- attempts to set up more
332 *	than one will cause the previous one to get closed.
333 *
334 * PROPERTYGRP_TX_START(entity_id_tx, entity_id) -> result
335 *	Makes entity_id_tx point to the same property group as entity_id,
336 *	then attempts to set up entity_id_tx as a transaction on that group.
337 *	entity_id and entity_id_tx must be distinct.  On failure, entity_id_tx
338 *	is reset.
339 *
340 * PROPERTYGRP_TX_COMMIT(entity_id, data) -> result
341 *	Gives the actual steps to follow, and attempts to commit them.
342 *
343 * CLIENT_ADD_NOTIFY(type, pattern) -> result
344 *	Adds a new property group name or type pattern to the notify list
345 *	(see CLIENT_WAIT).  If successful, takes effect immediately.
346 *
347 * CLIENT_WAIT(entity_id) -> result, fmri
348 *	Waits for a change to a propertygroup that matches the patterns
349 *	set up using CLIENT_ADD_NOTIFY, and puts the resultant propertygroup
350 *	in entity_id.  Note that if an error occurs, you can loose
351 *	notifications.  Either entity_id is set to a changed propertygroup,
352 *	or fmri is a non-zero-length string identifying a deleted thing.
353 *
354 * BACKUP(name) -> result
355 *	Backs up the persistant repository with a particular name.
356 */
357
358#include <door.h>
359#include <stddef.h>
360#include <sys/sysmacros.h>
361
362#ifdef	__cplusplus
363extern "C" {
364#endif
365
366/*
367 * svc.configd initial protocol details
368 */
369#define	REPOSITORY_DOOR_BASEVER	(('R' << 24) | ('e' << 16) | ('p' << 8))
370#define	REPOSITORY_DOOR_NAME	"/etc/svc/volatile/repository_door"
371#define	REPOSITORY_DOOR_COOKIE	((void *)REPOSITORY_DOOR_BASEVER)
372
373#define	REPOSITORY_BOOT_BACKUP	((const char *)"boot")
374
375/*
376 * This value should be incremented any time the protocol changes.  When in
377 * doubt, bump it.
378 */
379#define	REPOSITORY_DOOR_VERSION			(19 + REPOSITORY_DOOR_BASEVER)
380
381/*
382 * flags for rdr_flags
383 */
384#define	REPOSITORY_DOOR_FLAG_DEBUG		0x00000001	/* rdr_debug */
385
386#define	REPOSITORY_DOOR_FLAG_ALL		0x00000001	/* all flags */
387
388/*
389 * Request IDs
390 */
391enum repository_door_requestid {
392	REPOSITORY_DOOR_REQUEST_CONNECT = (('M' << 8) | 1)
393};
394
395enum repository_door_statusid {
396	REPOSITORY_DOOR_SUCCESS			= 0,
397	REPOSITORY_DOOR_FAIL_BAD_REQUEST	= 1,
398	REPOSITORY_DOOR_FAIL_VERSION_MISMATCH	= 2,
399	REPOSITORY_DOOR_FAIL_BAD_FLAG		= 3,
400	REPOSITORY_DOOR_FAIL_NO_RESOURCES	= 4,
401	REPOSITORY_DOOR_FAIL_PERMISSION_DENIED	= 5
402};
403
404/*
405 * You may only add elements to the end of this structure.
406 */
407typedef struct repository_door_request {
408	uint32_t rdr_version;			/* must be first element */
409	enum repository_door_requestid rdr_request;
410	uint32_t rdr_flags;
411	uint32_t rdr_debug;
412} repository_door_request_t;
413
414typedef struct repository_door_response {
415	enum repository_door_statusid rdr_status;
416} repository_door_response_t;
417
418/*
419 * Client interface.  Used on doors returned by REQUEST_CONNECT
420 */
421
422#define	REP_PROTOCOL_NAME_LEN		120	/* maximum name length */
423#define	REP_PROTOCOL_VALUE_LEN		4096	/* maximum value length */
424
425#define	REP_PROTOCOL_FMRI_LEN		(6 * REP_PROTOCOL_NAME_LEN)
426
427#define	REP_PROTOCOL_BASE		('C' << 8)
428
429/*
430 * Request codes
431 */
432enum rep_protocol_requestid {
433	REP_PROTOCOL_CLOSE		= REP_PROTOCOL_BASE,
434
435	REP_PROTOCOL_ENTITY_SETUP,
436	REP_PROTOCOL_ENTITY_NAME,
437	REP_PROTOCOL_ENTITY_PARENT_TYPE,
438	REP_PROTOCOL_ENTITY_GET_CHILD,
439	REP_PROTOCOL_ENTITY_GET_PARENT,
440	REP_PROTOCOL_ENTITY_GET,
441	REP_PROTOCOL_ENTITY_UPDATE,
442	REP_PROTOCOL_ENTITY_CREATE_CHILD,
443	REP_PROTOCOL_ENTITY_CREATE_PG,
444	REP_PROTOCOL_ENTITY_DELETE,
445	REP_PROTOCOL_ENTITY_RESET,
446	REP_PROTOCOL_ENTITY_TEARDOWN,
447
448	REP_PROTOCOL_ITER_SETUP,
449	REP_PROTOCOL_ITER_START,
450	REP_PROTOCOL_ITER_READ,
451	REP_PROTOCOL_ITER_READ_VALUE,
452	REP_PROTOCOL_ITER_RESET,
453	REP_PROTOCOL_ITER_TEARDOWN,
454
455	REP_PROTOCOL_NEXT_SNAPLEVEL,
456
457	REP_PROTOCOL_SNAPSHOT_TAKE,
458	REP_PROTOCOL_SNAPSHOT_TAKE_NAMED,
459	REP_PROTOCOL_SNAPSHOT_ATTACH,
460
461	REP_PROTOCOL_PROPERTY_GET_TYPE,
462	REP_PROTOCOL_PROPERTY_GET_VALUE,
463
464	REP_PROTOCOL_PROPERTYGRP_SETUP_WAIT,
465	REP_PROTOCOL_PROPERTYGRP_TX_START,
466	REP_PROTOCOL_PROPERTYGRP_TX_COMMIT,
467
468	REP_PROTOCOL_CLIENT_ADD_NOTIFY,
469	REP_PROTOCOL_CLIENT_WAIT,
470
471	REP_PROTOCOL_BACKUP,
472
473	REP_PROTOCOL_MAX_REQUEST
474};
475
476/*
477 * Response codes.  These are returned to the client, and the errors are
478 * translated into scf_error_t's by libscf (see proto_error()).
479 */
480typedef int32_t rep_protocol_responseid_t;
481enum rep_protocol_responseid {
482	REP_PROTOCOL_SUCCESS =			0,
483	/* iterators: No more values. */
484	REP_PROTOCOL_DONE =			1,
485
486	/* Request from client was malformed. */
487	REP_PROTOCOL_FAIL_BAD_REQUEST =		-1,
488	/* Prerequisite call has not been made. */
489	REP_PROTOCOL_FAIL_MISORDERED =		-2,
490	/* Register for ID has not been created. */
491	REP_PROTOCOL_FAIL_UNKNOWN_ID =		-3,
492	/* Out of memory or other resource. */
493	REP_PROTOCOL_FAIL_NO_RESOURCES =	-4,
494	/* Type argument is invalid. */
495	REP_PROTOCOL_FAIL_INVALID_TYPE =	-5,
496	/* Requested object does not exist. */
497	REP_PROTOCOL_FAIL_NOT_FOUND =		-6,
498	/* Register for given ID does not point to an object. */
499	REP_PROTOCOL_FAIL_NOT_SET =		-7,
500
501	/* Requested name is longer than supplied buffer. */
502	REP_PROTOCOL_FAIL_TRUNCATED =		-8,
503	/* Operation requires different type. */
504	REP_PROTOCOL_FAIL_TYPE_MISMATCH =	-9,
505
506	/* Changeable object has been changed since last update. */
507	REP_PROTOCOL_FAIL_NOT_LATEST =		-10,
508	/* Creation failed because object with given name exists. */
509	REP_PROTOCOL_FAIL_EXISTS =		-11,
510	/* Transaction is invalid. */
511	REP_PROTOCOL_FAIL_BAD_TX =		-12,
512	/* Operation is not applicable to indicated object. */
513	REP_PROTOCOL_FAIL_NOT_APPLICABLE =	-13,
514	/* Two IDs for operation were unexpectedly equal. */
515	REP_PROTOCOL_FAIL_DUPLICATE_ID =	-14,
516
517	/* Permission denied. */
518	REP_PROTOCOL_FAIL_PERMISSION_DENIED =	-15,
519	/* Backend does not exist or otherwise refused access. */
520	REP_PROTOCOL_FAIL_BACKEND_ACCESS =	-16,
521	/* Backend is read-only. */
522	REP_PROTOCOL_FAIL_BACKEND_READONLY =	-17,
523
524	/* Object has been deleted. */
525	REP_PROTOCOL_FAIL_DELETED =		-18,
526
527	REP_PROTOCOL_FAIL_UNKNOWN =		-0xfd
528};
529
530/*
531 * Types
532 */
533typedef enum rep_protocol_entity {
534	REP_PROTOCOL_ENTITY_NONE,
535	REP_PROTOCOL_ENTITY_SCOPE,
536	REP_PROTOCOL_ENTITY_SERVICE,
537	REP_PROTOCOL_ENTITY_INSTANCE,
538	REP_PROTOCOL_ENTITY_SNAPSHOT,
539	REP_PROTOCOL_ENTITY_SNAPLEVEL,
540	REP_PROTOCOL_ENTITY_PROPERTYGRP,
541	REP_PROTOCOL_ENTITY_CPROPERTYGRP,	/* "composed" property group */
542	REP_PROTOCOL_ENTITY_PROPERTY,
543	REP_PROTOCOL_ENTITY_VALUE,
544
545	REP_PROTOCOL_ENTITY_MAX
546} rep_protocol_entity_t;
547
548typedef enum rep_protocol_value_type {
549	REP_PROTOCOL_TYPE_INVALID	= '\0',
550	REP_PROTOCOL_TYPE_BOOLEAN	= 'b',
551	REP_PROTOCOL_TYPE_COUNT		= 'c',
552	REP_PROTOCOL_TYPE_INTEGER	= 'i',
553	REP_PROTOCOL_TYPE_TIME		= 't',
554	REP_PROTOCOL_TYPE_STRING	= 's',
555	REP_PROTOCOL_TYPE_OPAQUE	= 'o',
556
557	REP_PROTOCOL_SUBTYPE_USTRING	= REP_PROTOCOL_TYPE_STRING|('u' << 8),
558	REP_PROTOCOL_SUBTYPE_URI	= REP_PROTOCOL_TYPE_STRING|('U' << 8),
559	REP_PROTOCOL_SUBTYPE_FMRI	= REP_PROTOCOL_TYPE_STRING|('f' << 8),
560
561	REP_PROTOCOL_SUBTYPE_HOST	= REP_PROTOCOL_TYPE_STRING|('h' << 8),
562	REP_PROTOCOL_SUBTYPE_HOSTNAME	= REP_PROTOCOL_TYPE_STRING|('N' << 8),
563	REP_PROTOCOL_SUBTYPE_NETADDR_V4	= REP_PROTOCOL_TYPE_STRING|('4' << 8),
564	REP_PROTOCOL_SUBTYPE_NETADDR_V6	= REP_PROTOCOL_TYPE_STRING|('6' << 8)
565} rep_protocol_value_type_t;
566
567
568#define	REP_PROTOCOL_BASE_TYPE(t)	((t) & 0x00ff)
569#define	REP_PROTOCOL_SUBTYPE(t)		(((t) & 0xff00) >> 8)
570
571/*
572 * Request structures
573 */
574typedef struct rep_protocol_request {
575	enum rep_protocol_requestid rpr_request;
576} rep_protocol_request_t;
577
578struct rep_protocol_iter_request {
579	enum rep_protocol_requestid rpr_request;
580	uint32_t rpr_iterid;
581};
582
583struct rep_protocol_iter_start {
584	enum rep_protocol_requestid rpr_request;	/* ITER_START */
585	uint32_t rpr_iterid;
586
587	uint32_t rpr_entity;
588	uint32_t rpr_itertype;
589	uint32_t rpr_flags;
590	char	rpr_pattern[REP_PROTOCOL_NAME_LEN];
591};
592#define	RP_ITER_START_ALL	0x00000001	/* ignore pattern, match all */
593#define	RP_ITER_START_EXACT	0x00000002	/* exact match with pattern */
594#define	RP_ITER_START_PGTYPE	0x00000003	/* exact match pg type */
595#define	RP_ITER_START_FILT_MASK	0x00000003
596#define	RP_ITER_START_COMPOSED	0x00000004	/* composed */
597
598struct rep_protocol_iter_read {
599	enum rep_protocol_requestid rpr_request;	/* ITER_READ */
600	uint32_t rpr_iterid;
601	uint32_t rpr_sequence;		/* client increments upon success */
602	uint32_t rpr_entityid;		/* entity to write result to */
603};
604
605struct rep_protocol_iter_read_value {
606	enum rep_protocol_requestid rpr_request;	/* ITER_READ_VALUE */
607	uint32_t rpr_iterid;
608	uint32_t rpr_sequence;		/* client increments upon success */
609};
610
611struct rep_protocol_entity_setup {
612	enum rep_protocol_requestid rpr_request;	/* ENTITY_SETUP */
613	uint32_t rpr_entityid;
614	uint32_t rpr_entitytype;
615};
616
617struct rep_protocol_entity_name {
618	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
619	uint32_t rpr_entityid;
620	uint32_t rpr_answertype;
621};
622#define	RP_ENTITY_NAME_NAME			0
623#define	RP_ENTITY_NAME_PGTYPE			1
624#define	RP_ENTITY_NAME_PGFLAGS			2
625#define	RP_ENTITY_NAME_SNAPLEVEL_SCOPE		3
626#define	RP_ENTITY_NAME_SNAPLEVEL_SERVICE	4
627#define	RP_ENTITY_NAME_SNAPLEVEL_INSTANCE	5
628#define	RP_ENTITY_NAME_PGREADPROT		6
629
630struct rep_protocol_entity_update {
631	enum rep_protocol_requestid rpr_request;	/* ENTITY_UPDATE */
632	uint32_t rpr_entityid;
633	uint32_t rpr_changeid;
634};
635
636struct rep_protocol_entity_parent_type {
637	enum rep_protocol_requestid rpr_request;	/* ENTITY_PARENT_TYPE */
638	uint32_t rpr_entityid;
639};
640
641struct rep_protocol_entity_parent {
642	enum rep_protocol_requestid rpr_request;	/* ENTITY_GET_PARENT */
643	uint32_t rpr_entityid;
644	uint32_t rpr_outid;
645};
646
647struct rep_protocol_entity_get {
648	enum rep_protocol_requestid rpr_request;	/* ENTITY_SET */
649	uint32_t rpr_entityid;
650	uint32_t rpr_object;
651};
652#define	RP_ENTITY_GET_INVALIDATE	1
653#define	RP_ENTITY_GET_MOST_LOCAL_SCOPE	2
654
655struct rep_protocol_entity_create_child {
656	enum rep_protocol_requestid rpr_request; /* ENTITY_CREATE_CHILD */
657	uint32_t rpr_entityid;
658	uint32_t rpr_childtype;
659	uint32_t rpr_childid;
660	uint32_t rpr_changeid;
661	char	rpr_name[REP_PROTOCOL_NAME_LEN];
662};
663
664struct rep_protocol_entity_create_pg {
665	enum rep_protocol_requestid rpr_request; /* ENTITY_CREATE_PG */
666	uint32_t rpr_entityid;
667	uint32_t rpr_childtype;
668	uint32_t rpr_childid;
669	uint32_t rpr_changeid;
670	char	rpr_name[REP_PROTOCOL_NAME_LEN];
671	char	rpr_type[REP_PROTOCOL_NAME_LEN];
672	uint32_t rpr_flags;
673};
674
675struct rep_protocol_entity_get_child {
676	enum rep_protocol_requestid rpr_request;	/* ENTITY_GET_CHILD */
677	uint32_t rpr_entityid;
678	uint32_t rpr_childid;
679	char	rpr_name[REP_PROTOCOL_NAME_LEN];
680};
681
682struct rep_protocol_entity_delete {
683	enum rep_protocol_requestid rpr_request; /* ENTITY_DELETE_CHILD */
684	uint32_t rpr_entityid;
685	uint32_t rpr_changeid;
686};
687
688struct rep_protocol_entity_reset {
689	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
690	uint32_t rpr_entityid;
691};
692
693struct rep_protocol_entity_request {
694	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
695	uint32_t rpr_entityid;
696};
697
698struct rep_protocol_entity_teardown {
699	enum rep_protocol_requestid rpr_request;	/* ENTITY_TEARDOWN */
700	uint32_t rpr_entityid;
701};
702
703struct rep_protocol_entity_pair {
704	enum rep_protocol_requestid rpr_request;	/* NEXT_SNAPLEVEL */
705	uint32_t rpr_entity_src;
706	uint32_t rpr_entity_dst;
707};
708
709struct rep_protocol_transaction_start {
710	enum rep_protocol_requestid rpr_request;	/* TX_SETUP */
711	uint32_t rpr_entityid_tx;		/* property group tx entity */
712	uint32_t rpr_entityid;			/* property group entity */
713};
714
715struct rep_protocol_transaction_commit {
716	enum rep_protocol_requestid rpr_request; /* TX_COMMIT */
717	uint32_t rpr_entityid;
718	uint32_t rpr_size;			/* size of entire structure */
719	uint8_t rpr_cmd[1];
720};
721
722#define	REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(sz) \
723	    (offsetof(struct rep_protocol_transaction_commit, rpr_cmd[sz]))
724
725#define	REP_PROTOCOL_TRANSACTION_COMMIT_MIN_SIZE \
726	    REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(0)
727
728enum rep_protocol_transaction_action {
729	REP_PROTOCOL_TX_ENTRY_INVALID,	/* N/A */
730	REP_PROTOCOL_TX_ENTRY_NEW,	/* new property */
731	REP_PROTOCOL_TX_ENTRY_CLEAR,	/* clear old property */
732	REP_PROTOCOL_TX_ENTRY_REPLACE,	/* change type of old property */
733	REP_PROTOCOL_TX_ENTRY_DELETE	/* delete property (no values) */
734};
735
736struct rep_protocol_transaction_cmd {
737	enum	rep_protocol_transaction_action rptc_action;
738	uint32_t rptc_type;
739	uint32_t rptc_size;		/* size of entire structure */
740	uint32_t rptc_name_len;
741	uint8_t	rptc_data[1];
742};
743
744#define	REP_PROTOCOL_TRANSACTION_CMD_SIZE(sz) \
745	    (offsetof(struct rep_protocol_transaction_cmd, rptc_data[sz]))
746
747#define	REP_PROTOCOL_TRANSACTION_CMD_MIN_SIZE \
748	    REP_PROTOCOL_TRANSACTION_CMD_SIZE(0)
749
750#define	TX_SIZE(x)	P2ROUNDUP((x), sizeof (uint32_t))
751
752struct rep_protocol_transaction_request {
753	enum rep_protocol_requestid rpr_request; /* SETUP, ABORT or TEARDOWN */
754	uint32_t rpr_txid;
755};
756
757struct rep_protocol_property_request {
758	enum rep_protocol_requestid rpr_request;
759	uint32_t rpr_entityid;
760};
761
762struct rep_protocol_propertygrp_request {
763	enum rep_protocol_requestid rpr_request;
764	uint32_t rpr_entityid;
765};
766
767struct rep_protocol_notify_request {
768	enum rep_protocol_requestid rpr_request;
769	uint32_t rpr_type;
770	char	rpr_pattern[REP_PROTOCOL_NAME_LEN];
771};
772#define	REP_PROTOCOL_NOTIFY_PGNAME 1
773#define	REP_PROTOCOL_NOTIFY_PGTYPE 2
774
775struct rep_protocol_wait_request {
776	enum rep_protocol_requestid rpr_request;
777	uint32_t rpr_entityid;
778};
779
780struct rep_protocol_snapshot_take {
781	enum rep_protocol_requestid rpr_request;	/* SNAPSHOT_TAKE */
782	uint32_t rpr_entityid_src;
783	uint32_t rpr_entityid_dest;
784	int	rpr_flags;
785	char	rpr_name[REP_PROTOCOL_NAME_LEN];
786};
787#define	REP_SNAPSHOT_NEW	0x00000001
788#define	REP_SNAPSHOT_ATTACH	0x00000002
789
790struct rep_protocol_snapshot_take_named {
791	enum rep_protocol_requestid rpr_request; /* SNAPSHOT_TAKE_NAMED */
792	uint32_t rpr_entityid_src;
793	uint32_t rpr_entityid_dest;
794	char	rpr_svcname[REP_PROTOCOL_NAME_LEN];
795	char	rpr_instname[REP_PROTOCOL_NAME_LEN];
796	char	rpr_name[REP_PROTOCOL_NAME_LEN];
797};
798
799struct rep_protocol_snapshot_attach {
800	enum rep_protocol_requestid rpr_request;	/* SNAPSHOT_ATTACH */
801	uint32_t rpr_entityid_src;
802	uint32_t rpr_entityid_dest;
803};
804
805struct rep_protocol_backup_request {
806	enum rep_protocol_requestid rpr_request;	/* BACKUP */
807	uint32_t rpr_changeid;
808	char rpr_name[REP_PROTOCOL_NAME_LEN];
809};
810
811/*
812 * Response structures
813 */
814typedef struct rep_protocol_response {
815	rep_protocol_responseid_t rpr_response;
816} rep_protocol_response_t;
817
818struct rep_protocol_integer_response {
819	rep_protocol_responseid_t rpr_response;
820	uint32_t rpr_value;
821};
822
823struct rep_protocol_name_response {	/* response to ENTITY_NAME */
824	rep_protocol_responseid_t rpr_response;
825	char rpr_name[REP_PROTOCOL_NAME_LEN];
826};
827
828struct rep_protocol_fmri_response {
829	rep_protocol_responseid_t rpr_response;
830	char rpr_fmri[REP_PROTOCOL_FMRI_LEN];
831};
832
833struct rep_protocol_value_response {
834	rep_protocol_responseid_t rpr_response;
835	rep_protocol_value_type_t rpr_type;
836	char			rpr_value[2 * REP_PROTOCOL_VALUE_LEN + 1];
837};
838
839#ifdef	__cplusplus
840}
841#endif
842
843#endif	/* _REPCACHE_PROTOCOL_H */
844