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