repcache_protocol.h revision 5405:f7a026c6d133
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 * SET_ANNOTATION(operation, file)
358 *	Set up a security audit annotation event.  operation is the name of
359 *	the operation that is being annotated, and file is the file being
360 *	processed.  This will be used to mark operations which comprise
361 *	multiple primitive operations such as svccfg import.
362 */
363
364#include <door.h>
365#include <stddef.h>
366#include <sys/sysmacros.h>
367
368#ifdef	__cplusplus
369extern "C" {
370#endif
371
372/*
373 * svc.configd initial protocol details
374 */
375#define	REPOSITORY_DOOR_BASEVER	(('R' << 24) | ('e' << 16) | ('p' << 8))
376#define	REPOSITORY_DOOR_NAME	"/etc/svc/volatile/repository_door"
377#define	REPOSITORY_DOOR_COOKIE	((void *)REPOSITORY_DOOR_BASEVER)
378
379#define	REPOSITORY_BOOT_BACKUP	((const char *)"boot")
380
381/*
382 * This value should be incremented any time the protocol changes.  When in
383 * doubt, bump it.
384 */
385#define	REPOSITORY_DOOR_VERSION			(20 + REPOSITORY_DOOR_BASEVER)
386
387/*
388 * flags for rdr_flags
389 */
390#define	REPOSITORY_DOOR_FLAG_DEBUG		0x00000001	/* rdr_debug */
391
392#define	REPOSITORY_DOOR_FLAG_ALL		0x00000001	/* all flags */
393
394/*
395 * Request IDs
396 */
397enum repository_door_requestid {
398	REPOSITORY_DOOR_REQUEST_CONNECT = (('M' << 8) | 1)
399};
400
401enum repository_door_statusid {
402	REPOSITORY_DOOR_SUCCESS			= 0,
403	REPOSITORY_DOOR_FAIL_BAD_REQUEST	= 1,
404	REPOSITORY_DOOR_FAIL_VERSION_MISMATCH	= 2,
405	REPOSITORY_DOOR_FAIL_BAD_FLAG		= 3,
406	REPOSITORY_DOOR_FAIL_NO_RESOURCES	= 4,
407	REPOSITORY_DOOR_FAIL_PERMISSION_DENIED	= 5
408};
409
410/*
411 * You may only add elements to the end of this structure.
412 */
413typedef struct repository_door_request {
414	uint32_t rdr_version;			/* must be first element */
415	enum repository_door_requestid rdr_request;
416	uint32_t rdr_flags;
417	uint32_t rdr_debug;
418} repository_door_request_t;
419
420typedef struct repository_door_response {
421	enum repository_door_statusid rdr_status;
422} repository_door_response_t;
423
424/*
425 * Client interface.  Used on doors returned by REQUEST_CONNECT
426 */
427
428#define	REP_PROTOCOL_NAME_LEN		120	/* maximum name length */
429#define	REP_PROTOCOL_VALUE_LEN		4096	/* maximum value length */
430
431#define	REP_PROTOCOL_FMRI_LEN		(6 * REP_PROTOCOL_NAME_LEN)
432
433#define	REP_PROTOCOL_BASE		('C' << 8)
434
435/*
436 * Request codes
437 */
438enum rep_protocol_requestid {
439	REP_PROTOCOL_CLOSE		= REP_PROTOCOL_BASE,
440
441	REP_PROTOCOL_ENTITY_SETUP,
442	REP_PROTOCOL_ENTITY_NAME,
443	REP_PROTOCOL_ENTITY_PARENT_TYPE,
444	REP_PROTOCOL_ENTITY_GET_CHILD,
445	REP_PROTOCOL_ENTITY_GET_PARENT,
446	REP_PROTOCOL_ENTITY_GET,
447	REP_PROTOCOL_ENTITY_UPDATE,
448	REP_PROTOCOL_ENTITY_CREATE_CHILD,
449	REP_PROTOCOL_ENTITY_CREATE_PG,
450	REP_PROTOCOL_ENTITY_DELETE,
451	REP_PROTOCOL_ENTITY_RESET,
452	REP_PROTOCOL_ENTITY_TEARDOWN,
453
454	REP_PROTOCOL_ITER_SETUP,
455	REP_PROTOCOL_ITER_START,
456	REP_PROTOCOL_ITER_READ,
457	REP_PROTOCOL_ITER_READ_VALUE,
458	REP_PROTOCOL_ITER_RESET,
459	REP_PROTOCOL_ITER_TEARDOWN,
460
461	REP_PROTOCOL_NEXT_SNAPLEVEL,
462
463	REP_PROTOCOL_SNAPSHOT_TAKE,
464	REP_PROTOCOL_SNAPSHOT_TAKE_NAMED,
465	REP_PROTOCOL_SNAPSHOT_ATTACH,
466
467	REP_PROTOCOL_PROPERTY_GET_TYPE,
468	REP_PROTOCOL_PROPERTY_GET_VALUE,
469
470	REP_PROTOCOL_PROPERTYGRP_SETUP_WAIT,
471	REP_PROTOCOL_PROPERTYGRP_TX_START,
472	REP_PROTOCOL_PROPERTYGRP_TX_COMMIT,
473
474	REP_PROTOCOL_CLIENT_ADD_NOTIFY,
475	REP_PROTOCOL_CLIENT_WAIT,
476
477	REP_PROTOCOL_BACKUP,
478
479	REP_PROTOCOL_SET_AUDIT_ANNOTATION,
480
481	REP_PROTOCOL_MAX_REQUEST
482};
483
484/*
485 * Response codes.  These are returned to the client, and the errors are
486 * translated into scf_error_t's by libscf (see proto_error()).
487 */
488typedef int32_t rep_protocol_responseid_t;
489enum rep_protocol_responseid {
490	REP_PROTOCOL_SUCCESS =			0,
491	/* iterators: No more values. */
492	REP_PROTOCOL_DONE =			1,
493
494	/* Request from client was malformed. */
495	REP_PROTOCOL_FAIL_BAD_REQUEST =		-1,
496	/* Prerequisite call has not been made. */
497	REP_PROTOCOL_FAIL_MISORDERED =		-2,
498	/* Register for ID has not been created. */
499	REP_PROTOCOL_FAIL_UNKNOWN_ID =		-3,
500	/* Out of memory or other resource. */
501	REP_PROTOCOL_FAIL_NO_RESOURCES =	-4,
502	/* Type argument is invalid. */
503	REP_PROTOCOL_FAIL_INVALID_TYPE =	-5,
504	/* Requested object does not exist. */
505	REP_PROTOCOL_FAIL_NOT_FOUND =		-6,
506	/* Register for given ID does not point to an object. */
507	REP_PROTOCOL_FAIL_NOT_SET =		-7,
508
509	/* Requested name is longer than supplied buffer. */
510	REP_PROTOCOL_FAIL_TRUNCATED =		-8,
511	/* Operation requires different type. */
512	REP_PROTOCOL_FAIL_TYPE_MISMATCH =	-9,
513
514	/* Changeable object has been changed since last update. */
515	REP_PROTOCOL_FAIL_NOT_LATEST =		-10,
516	/* Creation failed because object with given name exists. */
517	REP_PROTOCOL_FAIL_EXISTS =		-11,
518	/* Transaction is invalid. */
519	REP_PROTOCOL_FAIL_BAD_TX =		-12,
520	/* Operation is not applicable to indicated object. */
521	REP_PROTOCOL_FAIL_NOT_APPLICABLE =	-13,
522	/* Two IDs for operation were unexpectedly equal. */
523	REP_PROTOCOL_FAIL_DUPLICATE_ID =	-14,
524
525	/* Permission denied. */
526	REP_PROTOCOL_FAIL_PERMISSION_DENIED =	-15,
527	/* Backend does not exist or otherwise refused access. */
528	REP_PROTOCOL_FAIL_BACKEND_ACCESS =	-16,
529	/* Backend is read-only. */
530	REP_PROTOCOL_FAIL_BACKEND_READONLY =	-17,
531
532	/* Object has been deleted. */
533	REP_PROTOCOL_FAIL_DELETED =		-18,
534
535	REP_PROTOCOL_FAIL_UNKNOWN =		-0xfd
536};
537
538/*
539 * Types
540 */
541typedef enum rep_protocol_entity {
542	REP_PROTOCOL_ENTITY_NONE,
543	REP_PROTOCOL_ENTITY_SCOPE,
544	REP_PROTOCOL_ENTITY_SERVICE,
545	REP_PROTOCOL_ENTITY_INSTANCE,
546	REP_PROTOCOL_ENTITY_SNAPSHOT,
547	REP_PROTOCOL_ENTITY_SNAPLEVEL,
548	REP_PROTOCOL_ENTITY_PROPERTYGRP,
549	REP_PROTOCOL_ENTITY_CPROPERTYGRP,	/* "composed" property group */
550	REP_PROTOCOL_ENTITY_PROPERTY,
551	REP_PROTOCOL_ENTITY_VALUE,
552
553	REP_PROTOCOL_ENTITY_MAX
554} rep_protocol_entity_t;
555
556typedef enum rep_protocol_value_type {
557	REP_PROTOCOL_TYPE_INVALID	= '\0',
558	REP_PROTOCOL_TYPE_BOOLEAN	= 'b',
559	REP_PROTOCOL_TYPE_COUNT		= 'c',
560	REP_PROTOCOL_TYPE_INTEGER	= 'i',
561	REP_PROTOCOL_TYPE_TIME		= 't',
562	REP_PROTOCOL_TYPE_STRING	= 's',
563	REP_PROTOCOL_TYPE_OPAQUE	= 'o',
564
565	REP_PROTOCOL_SUBTYPE_USTRING	= REP_PROTOCOL_TYPE_STRING|('u' << 8),
566	REP_PROTOCOL_SUBTYPE_URI	= REP_PROTOCOL_TYPE_STRING|('U' << 8),
567	REP_PROTOCOL_SUBTYPE_FMRI	= REP_PROTOCOL_TYPE_STRING|('f' << 8),
568
569	REP_PROTOCOL_SUBTYPE_HOST	= REP_PROTOCOL_TYPE_STRING|('h' << 8),
570	REP_PROTOCOL_SUBTYPE_HOSTNAME	= REP_PROTOCOL_TYPE_STRING|('N' << 8),
571	REP_PROTOCOL_SUBTYPE_NETADDR_V4	= REP_PROTOCOL_TYPE_STRING|('4' << 8),
572	REP_PROTOCOL_SUBTYPE_NETADDR_V6	= REP_PROTOCOL_TYPE_STRING|('6' << 8)
573} rep_protocol_value_type_t;
574
575
576#define	REP_PROTOCOL_BASE_TYPE(t)	((t) & 0x00ff)
577#define	REP_PROTOCOL_SUBTYPE(t)		(((t) & 0xff00) >> 8)
578
579/*
580 * Request structures
581 */
582typedef struct rep_protocol_request {
583	enum rep_protocol_requestid rpr_request;
584} rep_protocol_request_t;
585
586struct rep_protocol_iter_request {
587	enum rep_protocol_requestid rpr_request;
588	uint32_t rpr_iterid;
589};
590
591struct rep_protocol_iter_start {
592	enum rep_protocol_requestid rpr_request;	/* ITER_START */
593	uint32_t rpr_iterid;
594
595	uint32_t rpr_entity;
596	uint32_t rpr_itertype;
597	uint32_t rpr_flags;
598	char	rpr_pattern[REP_PROTOCOL_NAME_LEN];
599};
600#define	RP_ITER_START_ALL	0x00000001	/* ignore pattern, match all */
601#define	RP_ITER_START_EXACT	0x00000002	/* exact match with pattern */
602#define	RP_ITER_START_PGTYPE	0x00000003	/* exact match pg type */
603#define	RP_ITER_START_FILT_MASK	0x00000003
604#define	RP_ITER_START_COMPOSED	0x00000004	/* composed */
605
606struct rep_protocol_iter_read {
607	enum rep_protocol_requestid rpr_request;	/* ITER_READ */
608	uint32_t rpr_iterid;
609	uint32_t rpr_sequence;		/* client increments upon success */
610	uint32_t rpr_entityid;		/* entity to write result to */
611};
612
613struct rep_protocol_iter_read_value {
614	enum rep_protocol_requestid rpr_request;	/* ITER_READ_VALUE */
615	uint32_t rpr_iterid;
616	uint32_t rpr_sequence;		/* client increments upon success */
617};
618
619struct rep_protocol_entity_setup {
620	enum rep_protocol_requestid rpr_request;	/* ENTITY_SETUP */
621	uint32_t rpr_entityid;
622	uint32_t rpr_entitytype;
623};
624
625struct rep_protocol_entity_name {
626	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
627	uint32_t rpr_entityid;
628	uint32_t rpr_answertype;
629};
630#define	RP_ENTITY_NAME_NAME			0
631#define	RP_ENTITY_NAME_PGTYPE			1
632#define	RP_ENTITY_NAME_PGFLAGS			2
633#define	RP_ENTITY_NAME_SNAPLEVEL_SCOPE		3
634#define	RP_ENTITY_NAME_SNAPLEVEL_SERVICE	4
635#define	RP_ENTITY_NAME_SNAPLEVEL_INSTANCE	5
636#define	RP_ENTITY_NAME_PGREADPROT		6
637
638struct rep_protocol_entity_update {
639	enum rep_protocol_requestid rpr_request;	/* ENTITY_UPDATE */
640	uint32_t rpr_entityid;
641	uint32_t rpr_changeid;
642};
643
644struct rep_protocol_entity_parent_type {
645	enum rep_protocol_requestid rpr_request;	/* ENTITY_PARENT_TYPE */
646	uint32_t rpr_entityid;
647};
648
649struct rep_protocol_entity_parent {
650	enum rep_protocol_requestid rpr_request;	/* ENTITY_GET_PARENT */
651	uint32_t rpr_entityid;
652	uint32_t rpr_outid;
653};
654
655struct rep_protocol_entity_get {
656	enum rep_protocol_requestid rpr_request;	/* ENTITY_SET */
657	uint32_t rpr_entityid;
658	uint32_t rpr_object;
659};
660#define	RP_ENTITY_GET_INVALIDATE	1
661#define	RP_ENTITY_GET_MOST_LOCAL_SCOPE	2
662
663struct rep_protocol_entity_create_child {
664	enum rep_protocol_requestid rpr_request; /* ENTITY_CREATE_CHILD */
665	uint32_t rpr_entityid;
666	uint32_t rpr_childtype;
667	uint32_t rpr_childid;
668	uint32_t rpr_changeid;
669	char	rpr_name[REP_PROTOCOL_NAME_LEN];
670};
671
672struct rep_protocol_entity_create_pg {
673	enum rep_protocol_requestid rpr_request; /* ENTITY_CREATE_PG */
674	uint32_t rpr_entityid;
675	uint32_t rpr_childtype;
676	uint32_t rpr_childid;
677	uint32_t rpr_changeid;
678	char	rpr_name[REP_PROTOCOL_NAME_LEN];
679	char	rpr_type[REP_PROTOCOL_NAME_LEN];
680	uint32_t rpr_flags;
681};
682
683struct rep_protocol_entity_get_child {
684	enum rep_protocol_requestid rpr_request;	/* ENTITY_GET_CHILD */
685	uint32_t rpr_entityid;
686	uint32_t rpr_childid;
687	char	rpr_name[REP_PROTOCOL_NAME_LEN];
688};
689
690struct rep_protocol_entity_delete {
691	enum rep_protocol_requestid rpr_request; /* ENTITY_DELETE_CHILD */
692	uint32_t rpr_entityid;
693	uint32_t rpr_changeid;
694};
695
696struct rep_protocol_entity_reset {
697	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
698	uint32_t rpr_entityid;
699};
700
701struct rep_protocol_entity_request {
702	enum rep_protocol_requestid rpr_request;	/* ENTITY_NAME */
703	uint32_t rpr_entityid;
704};
705
706struct rep_protocol_entity_teardown {
707	enum rep_protocol_requestid rpr_request;	/* ENTITY_TEARDOWN */
708	uint32_t rpr_entityid;
709};
710
711struct rep_protocol_entity_pair {
712	enum rep_protocol_requestid rpr_request;	/* NEXT_SNAPLEVEL */
713	uint32_t rpr_entity_src;
714	uint32_t rpr_entity_dst;
715};
716
717struct rep_protocol_transaction_start {
718	enum rep_protocol_requestid rpr_request;	/* TX_SETUP */
719	uint32_t rpr_entityid_tx;		/* property group tx entity */
720	uint32_t rpr_entityid;			/* property group entity */
721};
722
723struct rep_protocol_transaction_commit {
724	enum rep_protocol_requestid rpr_request; /* TX_COMMIT */
725	uint32_t rpr_entityid;
726	uint32_t rpr_size;			/* size of entire structure */
727	uint8_t rpr_cmd[1];
728};
729
730#define	REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(sz) \
731	    (offsetof(struct rep_protocol_transaction_commit, rpr_cmd[sz]))
732
733#define	REP_PROTOCOL_TRANSACTION_COMMIT_MIN_SIZE \
734	    REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(0)
735
736enum rep_protocol_transaction_action {
737	REP_PROTOCOL_TX_ENTRY_INVALID,	/* N/A */
738	REP_PROTOCOL_TX_ENTRY_NEW,	/* new property */
739	REP_PROTOCOL_TX_ENTRY_CLEAR,	/* clear old property */
740	REP_PROTOCOL_TX_ENTRY_REPLACE,	/* change type of old property */
741	REP_PROTOCOL_TX_ENTRY_DELETE	/* delete property (no values) */
742};
743
744struct rep_protocol_transaction_cmd {
745	enum	rep_protocol_transaction_action rptc_action;
746	uint32_t rptc_type;
747	uint32_t rptc_size;		/* size of entire structure */
748	uint32_t rptc_name_len;
749	uint8_t	rptc_data[1];
750};
751
752#define	REP_PROTOCOL_TRANSACTION_CMD_SIZE(sz) \
753	    (offsetof(struct rep_protocol_transaction_cmd, rptc_data[sz]))
754
755#define	REP_PROTOCOL_TRANSACTION_CMD_MIN_SIZE \
756	    REP_PROTOCOL_TRANSACTION_CMD_SIZE(0)
757
758#define	TX_SIZE(x)	P2ROUNDUP((x), sizeof (uint32_t))
759
760struct rep_protocol_transaction_request {
761	enum rep_protocol_requestid rpr_request; /* SETUP, ABORT or TEARDOWN */
762	uint32_t rpr_txid;
763};
764
765struct rep_protocol_property_request {
766	enum rep_protocol_requestid rpr_request;
767	uint32_t rpr_entityid;
768};
769
770struct rep_protocol_propertygrp_request {
771	enum rep_protocol_requestid rpr_request;
772	uint32_t rpr_entityid;
773};
774
775struct rep_protocol_notify_request {
776	enum rep_protocol_requestid rpr_request;
777	uint32_t rpr_type;
778	char	rpr_pattern[REP_PROTOCOL_NAME_LEN];
779};
780#define	REP_PROTOCOL_NOTIFY_PGNAME 1
781#define	REP_PROTOCOL_NOTIFY_PGTYPE 2
782
783struct rep_protocol_wait_request {
784	enum rep_protocol_requestid rpr_request;
785	uint32_t rpr_entityid;
786};
787
788struct rep_protocol_snapshot_take {
789	enum rep_protocol_requestid rpr_request;	/* SNAPSHOT_TAKE */
790	uint32_t rpr_entityid_src;
791	uint32_t rpr_entityid_dest;
792	int	rpr_flags;
793	char	rpr_name[REP_PROTOCOL_NAME_LEN];
794};
795#define	REP_SNAPSHOT_NEW	0x00000001
796#define	REP_SNAPSHOT_ATTACH	0x00000002
797
798struct rep_protocol_snapshot_take_named {
799	enum rep_protocol_requestid rpr_request; /* SNAPSHOT_TAKE_NAMED */
800	uint32_t rpr_entityid_src;
801	uint32_t rpr_entityid_dest;
802	char	rpr_svcname[REP_PROTOCOL_NAME_LEN];
803	char	rpr_instname[REP_PROTOCOL_NAME_LEN];
804	char	rpr_name[REP_PROTOCOL_NAME_LEN];
805};
806
807struct rep_protocol_snapshot_attach {
808	enum rep_protocol_requestid rpr_request;	/* SNAPSHOT_ATTACH */
809	uint32_t rpr_entityid_src;
810	uint32_t rpr_entityid_dest;
811};
812
813struct rep_protocol_backup_request {
814	enum rep_protocol_requestid rpr_request;	/* BACKUP */
815	uint32_t rpr_changeid;
816	char rpr_name[REP_PROTOCOL_NAME_LEN];
817};
818
819struct rep_protocol_annotation {
820	enum rep_protocol_requestid rpr_request;	/* SET_ANNOTATION */
821	char rpr_operation[REP_PROTOCOL_NAME_LEN];
822	char rpr_file[MAXPATHLEN];
823};
824
825/*
826 * Response structures
827 */
828typedef struct rep_protocol_response {
829	rep_protocol_responseid_t rpr_response;
830} rep_protocol_response_t;
831
832struct rep_protocol_integer_response {
833	rep_protocol_responseid_t rpr_response;
834	uint32_t rpr_value;
835};
836
837struct rep_protocol_name_response {	/* response to ENTITY_NAME */
838	rep_protocol_responseid_t rpr_response;
839	char rpr_name[REP_PROTOCOL_NAME_LEN];
840};
841
842struct rep_protocol_fmri_response {
843	rep_protocol_responseid_t rpr_response;
844	char rpr_fmri[REP_PROTOCOL_FMRI_LEN];
845};
846
847struct rep_protocol_value_response {
848	rep_protocol_responseid_t rpr_response;
849	rep_protocol_value_type_t rpr_type;
850	char			rpr_value[2 * REP_PROTOCOL_VALUE_LEN + 1];
851};
852
853#ifdef	__cplusplus
854}
855#endif
856
857#endif	/* _REPCACHE_PROTOCOL_H */
858