File:  [DragonFly] / src / sys / sys / caps.h
Revision 1.5: download - view: text, annotated - select for diffs
Sat Mar 6 22:14:16 2004 UTC (10 years, 9 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Additional CAPS IPC work.  Add additional system calls to allow a CAPS
server to set a generation number and a CAPS client to query it, which can
be used for any purpose but which is intended to allow a server to tell its
clients to invalidate their caches.

Add missing fork-handling code.  CAPS links are only good on a thread-by-thread
basis.  When a process forks/rforks/clones any active CAPS links will be
created as dummy entries in the forked process, causing CAPS syscalls to
return ENOTCONN.   This allows code based on CAPS to detect when it has been
forked so it can re-connect to the service.

Make a slight change to the API.  caps_sys_put() now returns an immediate
ENOTCONN if it forked.  Note that userland CAPS code must still deal with
the case where a message has been sent and the connection is lost before the
reply is returned.  The kernel automatically replies unreplied messages
with 0-length data in these cases.

Add additional flags to the API, including one that allows a client to
block when connecting to a non-existant service.

/*
 * SYS/CAPS.H
 *
 *	Implements an architecture independant Capability Service API
 * 
 * $DragonFly: src/sys/sys/caps.h,v 1.5 2004/03/06 22:14:16 dillon Exp $
 */

#ifndef _SYS_CAPS_H_
#define _SYS_CAPS_H_

#ifndef _SYS_TYPES_H_
#include <sys/types.h>
#endif
#ifndef _SYS_MSGPORT_H_
#include <sys/msgport.h>
#endif

typedef enum caps_msg_state { 
	CAPMS_REQUEST, 
	CAPMS_REQUEST_RETRY, 	/* internal / FUTURE */
	CAPMS_REPLY, 
	CAPMS_REPLY_RETRY,	/* internal / FUGURE */
	CAPMS_DISPOSE
} caps_msg_state_t;

typedef struct caps_msgid {
	off_t			c_id;
	caps_msg_state_t	c_state;
	int			c_reserved01;
} *caps_msgid_t;

typedef enum caps_type { 
	CAPT_UNKNOWN, CAPT_CLIENT, CAPT_SERVICE, CAPT_REMOTE, CAPT_FORKED
} caps_type_t;

typedef int64_t	caps_gen_t;

/*
 * Note: upper 16 bits reserved for kernel use
 */
#define CAPF_UFLAGS	0xFFFF
#define CAPF_USER	0x0001
#define CAPF_GROUP	0x0002
#define CAPF_WORLD	0x0004
#define CAPF_EXCL	0x0008
#define CAPF_ANYCLIENT	(CAPF_USER|CAPF_GROUP|CAPF_WORLD)
#define CAPF_WCRED	0x0010	/* waiting for cred */
#define CAPF_NOFORK	0x0020	/* do not create a dummy entry on fork */
#define CAPF_WAITSVC	0x0040	/* block if service not available */
/* FUTURE: CAPF_ASYNC - support async services */
/* FUTURE: CAPF_NOGROUPS - don't bother filling in the groups[] array */
/* FUTURE: CAPF_TERM - send termination request to existing service */
/* FUTURE: CAPF_TAKE - take over existing service's connections */
/* FUTURE: CAPF_DISPOSE_IMM - need immediate dispose wakeups */

/*
 * Abort codes
 */
#define CAPS_ABORT_NOTIMPL	0	/* abort not implemented, no action */
#define CAPS_ABORT_RETURNED	1	/* already returned, no action */
#define CAPS_ABORT_BEFORESERVER	2	/* caught before the server got it */
#define CAPS_ABORT_ATSERVER	3	/* server had retrieved message */

#define CAPF_ABORT_HARD		0x0001	/* rip out from under server (3) */

#define CAPS_MAXGROUPS	16
#define CAPS_MAXNAMELEN	64
#define CAPS_MAXINPROG	128

struct thread;

typedef struct caps_port {
	struct lwkt_port	cp_lport;
	int			cp_portid;	/* caps port id */
	int			cp_upcallid;	/* upcall id */
} *caps_port_t;

typedef struct caps_cred {
	pid_t			pid;
	uid_t			uid;
	uid_t			euid;
	gid_t			gid;
	int			ngroups;
	int			cacheid;
	gid_t			groups[CAPS_MAXGROUPS];
} *caps_cred_t;

#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)

struct caps_kmsg;

TAILQ_HEAD(caps_kmsg_queue, caps_kmsg);

/*
 * caps_kinfo -	Holds a client or service registration
 *
 * ci_msgpendq: holds the kernel copy of the message after it has been
 * 		sent to the local port.  The message is matched up against
 *		replies and automatically replied if the owner closes its 
 *		connection.
 */
typedef struct caps_kinfo {
	struct lwkt_port	ci_lport;	/* embedded local port */
	struct caps_kinfo	*ci_tdnext;	/* per-process list */
	struct caps_kinfo	*ci_hnext;	/* registration hash table */
	struct thread		*ci_td;		/* owner */
	struct caps_kmsg_queue	ci_msgpendq;	/* pending reply (just rcvd) */
	struct caps_kmsg_queue	ci_msguserq;	/* pending reply (user holds) */
	struct caps_kinfo	*ci_rcaps;	/* connected to remote */
	int			ci_cmsgcount;	/* client in-progress msgs */
	int			ci_id;
	int			ci_flags;
	int			ci_refs;
	int			ci_mrefs;	/* message (vmspace) refs */
	caps_type_t		ci_type;
	caps_gen_t		ci_gen;
	uid_t			ci_uid;
	gid_t			ci_gid;
	int			ci_namelen;
	char			ci_name[4];	/* variable length */
	/* ci_name must be last element */
} *caps_kinfo_t;

/* note: user flags are held in the low 16 bits */
#define CAPKF_TDLIST	0x00010000
#define CAPKF_HLIST	0x00020000
#define CAPKF_FLUSH	0x00040000
#define CAPKF_RCAPS	0x00080000
#define CAPKF_CLOSED	0x00100000
#define CAPKF_MWAIT	0x00200000

/*
 * Kernel caps message.  The kernel keepps track of messagse received,
 * undergoing processing by the service, and returned.  User-supplied data
 * is copied on reception rather then transmission.
 */
typedef struct caps_kmsg {
	TAILQ_ENTRY(caps_kmsg)	km_node;
	caps_kinfo_t		km_mcaps;	/* message sender */
	void			*km_umsg;	/* mcaps vmspace */
	int			km_umsg_size;	/* mcaps vmspace */
	struct caps_cred	km_ccr;		/* caps cred for msg */
	struct caps_msgid	km_msgid;
	int			km_flags;
} *caps_kmsg_t;

#define km_state	km_msgid.c_state

#define CAPKMF_ONUSERQ		0x0001
#define CAPKMF_ONPENDQ		0x0002
#define CAPKMF_REPLY		0x0004
#define CAPKMF_CDONE		0x0008
#define CAPKMF_PEEKED		0x0010
#define CAPKMF_ABORTED		0x0020

#endif

#ifdef _KERNEL

/*
 * kernel support
 */
void caps_exit(struct thread *td);
void caps_fork(struct proc *p1, struct proc *p2, int flags);

#else

/*
 * Userland API (libcaps)
 */
caps_port_t caps_service(const char *, uid_t, gid_t, mode_t, int);
caps_port_t caps_client(const char *, uid_t, gid_t, int);

/*
 * Syscall API
 */
int caps_sys_service(const char *, uid_t, gid_t, int, int);
int caps_sys_client(const char *, uid_t, gid_t, int, int);
off_t caps_sys_put(int, void *, int);
int caps_sys_reply(int, void *, int, off_t);
int caps_sys_get(int, void *, int, caps_msgid_t, caps_cred_t);
int caps_sys_wait(int, void *, int, caps_msgid_t, caps_cred_t);
int caps_sys_abort(int, off_t, int);
int caps_sys_setgen(int, caps_gen_t);
caps_gen_t caps_sys_getgen(int);

#endif

#endif