/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_SYSEVENT_IMPL_H #define _SYS_SYSEVENT_IMPL_H #include #include #include #ifdef __cplusplus extern "C" { #endif typedef uint64_t se_data_t; /* * The following data structure assist in loading and extracting event * header and attribute data into contiguous memory. Access to all typed * data done so on 64-bit boundaries. *Do Not* alter any of the structures * defined below without thorough thought and testing. */ /* Attribute name */ typedef struct se_name { int32_t name_sz; int32_t name_pad; se_data_t name; /* 64-bit aligned offset */ } se_name_t; /* Attribute value */ typedef struct se_value { int32_t value_type; /* data type */ int32_t value_sz; se_data_t value; /* data value - 64-bit aligned offset */ } se_value_t; /* sysevent internal attribute name-value pair stored in contiguous memory */ typedef struct sysevent_attr_impl { int32_t se_attr_sz; /* Size of attribute data */ int32_t se_attr_pad; /* pad */ se_data_t se_attr_name; /* name of data attribute */ se_data_t se_attr_val; /* value and type of data */ } sysevent_attr_impl_t; /* Attribute list states */ #define ATTR_DETACHED 0 #define ATTR_ATTACHED 1 /* * The following type definitions describe a sysevent object that is * generated by a call to sysevent_alloc and sent to userland. */ /* * sysevent event header information - * contained in every event generated. The header and the event * must remain 64-bit aligned. The header, up to the attribute * offset, can be contained in a single cache line. */ typedef struct sysevent_hdr { sysevent_id_t se_id; /* unique identifier */ uint32_t se_version; /* version of this data structure */ uint32_t se_flag; uint32_t se_class; /* event class id - reserved */ uint32_t se_subclass; /* event subclass id - reserved */ int32_t se_payload_sz; /* size of attr data + strings */ uint16_t se_subclass_off; /* offset to subclass string */ uint16_t se_pub_off; /* offset to publisher string */ uint64_t se_attr_off; /* pointer or offset to attr data */ } sysevent_hdr_t; /* sysevent event buffer - 64-bit aligned offsets */ typedef struct sys_event_impl { sysevent_hdr_t se_header; se_data_t se_class_name; /* class string in contig memory */ se_data_t se_subclass_name; /* subclass string in contig memory */ se_data_t se_pub; /* publisher string in contig mem */ se_data_t se_attr_buf; /* contiguous attribute memory */ } sysevent_impl_t; /* Helpful defines */ #define seh_version se_header.se_version #define seh_class se_header.se_class #define seh_subclass se_header.se_subclass #define seh_seq se_header.se_id.eid_seq #define seh_time se_header.se_id.eid_ts #define seh_subclass_off se_header.se_subclass_off #define seh_pub_off se_header.se_pub_off #define seh_attr_off se_header.se_attr_off #define seh_payload_sz se_header.se_payload_sz #define seh_flag se_header.se_flag /* Event buffer version */ #define SYS_EVENT_VERSION 0 /* Event buffer flags */ #define SE_PACKED_BUF 1 #define SYSEVENT_IMPL(ev) ((sysevent_impl_t *)(void *)(ev)) #define SE_VERSION(ev) (SYSEVENT_IMPL(ev)->seh_version) #define SE_CLASS(ev) (SYSEVENT_IMPL(ev)->seh_class) #define SE_SUBCLASS(ev) (SYSEVENT_IMPL(ev)->seh_subclass) #define SE_SEQ(ev) (SYSEVENT_IMPL(ev)->seh_seq) #define SE_TIME(ev) (SYSEVENT_IMPL(ev)->seh_time) #define SE_SUBCLASS_OFF(ev) (SYSEVENT_IMPL(ev)->seh_subclass_off) #define SE_PUB_OFF(ev) (SYSEVENT_IMPL(ev)->seh_pub_off) #define SE_PAYLOAD_SZ(ev) (SYSEVENT_IMPL(ev)->seh_payload_sz) #define SE_FLAG(ev) (SYSEVENT_IMPL(ev)->seh_flag) #define SE_SIZE(ev) (sizeof (sysevent_impl_t) + SE_PAYLOAD_SZ(ev)) #define SE_CLASS_NAME(ev) ((char *)&(SYSEVENT_IMPL(ev)->se_class_name)) #define SE_SUBCLASS_NAME(ev) ((char *)((caddr_t)(ev) + SE_SUBCLASS_OFF(ev))) #define SE_PUB_NAME(ev) ((char *)((caddr_t)(ev) + SE_PUB_OFF(ev))) /* * Attribute data can be stored in contiguous memory or * as a list of attribute data elements. The storage format is determined * by the SE_PACKED_BUF flag in the event buffer flags. * */ /* 64-bit boundary alignment function */ #define SE_ALIGN(x) ((((ulong_t)x) + 7ul) & ~7ul) /* Access to unpacked attribute list */ #define SE_ATTR_PTR(ev) (SYSEVENT_IMPL(ev)->seh_attr_off) /* Offset to packed attribute data */ #define SE_ATTR_OFF(ev) SE_PUB_OFF(ev) + SE_ALIGN(strlen(SE_PUB_NAME(ev)) + 1) /* syseventd door */ #define LOGEVENT_DOOR_UPCALL "/var/run/sysevent_door" /* * door upcall data structures */ typedef struct log_event_upcall_arg { int32_t retcode; int32_t pad; sysevent_impl_t buf; } log_event_upcall_arg_t; typedef struct log_eventq { struct log_eventq *next; log_event_upcall_arg_t arg; } log_eventq_t; /* Syseventd Channel structures */ #define MAX_CHAN 256 /* Maximum channels per system */ #define MAX_SUBSCRIBERS 100 /* Maximum subscribers per channel */ #define MAX_PUBLISHERS 1 /* Maximum publishers per channel */ /* * Channel-based subscription structures */ /* Class hashing defines */ #define CLASS_HASH_SZ 63 #define CLASS_HASH(class_name) ((hash_func(class_name) \ % CLASS_HASH_SZ) + 1) #define CHAN_HASH_SZ 32 typedef struct subclass_lst { struct subclass_lst *sl_next; char *sl_name; uchar_t sl_num[MAX_SUBSCRIBERS + 1]; } subclass_lst_t; typedef struct class_lst { struct class_lst *cl_next; char *cl_name; struct subclass_lst *cl_subclass_list; } class_lst_t; /* User/Kernel Structure to pass event registration modctl data */ typedef struct se_pubsub { uint32_t ps_buflen; uint32_t ps_channel_name_len; uint32_t ps_id; uint32_t ps_op; uint32_t ps_type; } se_pubsub_t; /* op defines */ #define SE_REGISTER 0 #define SE_UNREGISTER 1 #define SE_CLEANUP 2 #define SE_OPEN_REGISTRATION 3 #define SE_CLOSE_REGISTRATION 4 #define SE_BIND_REGISTRATION 5 #define SE_UNBIND_REGISTRATION 6 #define SE_GET_REGISTRATION 7 /* type defines */ #define SUBSCRIBER 0 #define PUBLISHER 1 /* nvpair names */ #define CLASS_NAME "class" #ifdef _KERNEL typedef struct sysevent_channel_descriptor { char *scd_channel_name; /* Name of channel */ struct sysevent_channel_descriptor *scd_next; int scd_ref_cnt; /* Reference count of channel opens */ id_space_t *scd_subscriber_cache; /* cache of subscriber ids */ id_space_t *scd_publisher_cache; /* cache of publisher ids */ uchar_t scd_subscriber_ids[MAX_SUBSCRIBERS + 1]; /* used sub ids */ uchar_t scd_publisher_ids[MAX_PUBLISHERS + 1]; /* used pub ids */ class_lst_t *scd_class_list_tbl[CLASS_HASH_SZ + 1]; } sysevent_channel_descriptor_t; /* * log_sysevent private interfaces */ extern void log_event_init(void); extern void log_sysevent_flushq(int, uint_t); extern int log_sysevent_filename(char *); extern int log_usr_sysevent(sysevent_t *, int, sysevent_id_t *); extern int log_sysevent_copyout_data(sysevent_id_t *, size_t, caddr_t); extern int log_sysevent_free_data(sysevent_id_t *); extern int log_sysevent_register(char *, char *, se_pubsub_t *); extern uint64_t log_sysevent_new_id(void); /* * Structures and definitions for general purpose event channels */ /* Limits */ #define EVCH_MAX_CHANNELS 1024 #define EVCH_MAX_BINDS_PER_CHANNEL 512 #define EVCH_MAX_SUBSCRIPTIONS 32 #define EVCH_SUBPOOLFACT 8 #define EVCH_DEFAULT_EVENTS 2000 #define EVCH_MAX_TRY_DELIVERY 3 /* Linkage element for evch_dlist_t lists */ typedef struct evch_dlelem { struct evch_dlelem *dl_next; struct evch_dlelem *dl_prev; } evch_dlelem_t; /* List head */ typedef struct { evch_dlelem_t dh_head; int dh_count; } evch_dlist_t; /* Placeholder for elements in a evch_squeue_t queue */ typedef struct evch_qelem { struct evch_qelem *q_next; void *q_objref; size_t q_objsize; } evch_qelem_t; /* Queue head data */ typedef struct { evch_qelem_t *sq_head; evch_qelem_t *sq_tail; uint32_t sq_count; uint32_t sq_highwm; } evch_squeue_t; /* * Defines for event queue routines */ #define EVQ_IGNORE 1 #define EVQ_DELIVER 2 #define EVQ_CONT 0 #define EVQ_AGAIN 1 #define EVQ_SLEEP 2 /* Call back routine typedefs */ typedef int (*filter_f)(void *, void *); typedef int (*deliver_f)(void *, void *); typedef int (*kerndlv_f)(void *, void *); typedef void (*destr_f)(void *, void *); typedef int (*compare_f)(evch_dlelem_t *, char *); /* * Event structure handled by evch_evq_* functions. Sysevent type events are * stored as the payload. */ typedef struct { uint32_t ge_size; /* Total size of event structure */ uint32_t ge_refcount; /* No of queues event is linked to */ destr_f ge_destruct; /* Destructor for event structure */ uint32_t *ge_dstcookie; /* Cookie for destructor function */ uchar_t ge_payload[1]; /* Placeholder for event data */ } evch_gevent_t; /* * Event queue descriptor */ typedef struct { evch_squeue_t eq_eventq; /* Protected by eq_dtmutex */ kt_did_t eq_thrid; /* Id delivery thread */ kmutex_t eq_queuemx; /* Protect. of this struct and ev q */ kcondvar_t eq_thrsleepcv; /* Delivery thread sleeps on empty q */ int eq_dactive; /* Event delivery is in progress */ kcondvar_t eq_dactivecv; /* Unsubscr. has to wait on this */ evch_dlist_t eq_subscr; /* Chain of all evch_evqsub_t */ uint32_t eq_nsleep; /* Statistic: Publisher set to sleep */ int eq_holdmode; /* Hold event delivery */ evch_gevent_t *eq_curevent; /* Event currently beeing delivered */ evch_qelem_t *eq_nextev; /* For iterating over events in a q */ kcondvar_t eq_onholdcv; /* To signal hold mode of deliv. thr. */ uchar_t eq_tabortflag; /* Request to abort delivery thread */ } evch_eventq_t; /* * Event queue per subscriber structure */ typedef struct { evch_dlelem_t su_link; filter_f su_filter; /* Event filter function pointer */ void *su_fcookie; /* cookie for event filter */ deliver_f su_callb; /* Event delivery callback */ void *su_cbcookie; /* callback cookie */ } evch_evqsub_t; /* Eveny delivery type */ #define EVCH_DELKERN 1 /* Kernel event delivery */ #define EVCH_DELDOOR 2 /* User event delivery via doors */ /* * Per channel subscriber data structure. Chained in a linked list to an * event channel and to a binding. */ typedef struct chsubd { evch_dlelem_t sd_link; /* Links all subscribers of this ch. */ struct chsubd *sd_subnxt; /* Links all subscr. for a binding */ char *sd_ident; /* Subscriber identifier */ evch_eventq_t *sd_queue; /* Event queue for this subscriber */ evch_evqsub_t *sd_msub; /* Main event queue subscr. */ char *sd_classname; /* Filter criteria */ size_t sd_clnsize; /* Size of sd_classname buffer */ evch_evqsub_t *sd_ssub; /* Subscriber queue subscr. */ int sd_type; /* Type of event delivery */ kerndlv_f sd_callback; /* Callback for kernel delivery */ void *sd_cbcookie; /* Cookie for kernel delivery */ door_handle_t sd_door; /* Door handle for user delivery */ int sd_active; /* Subscription is in use indicator */ pid_t sd_pid; /* PID of subscribing process */ uint8_t sd_persist; /* Persistent user land subscription */ uint8_t sd_dump; /* Dump with sysevent_evc_walk_* */ } evch_subd_t; /* * General purpose event channel descriptor structure. This is the main * structure for event subscribing, publishing, delivery to/from an event * channel. */ typedef struct { evch_dlelem_t ch_link; /* Must be first elem. of structure */ char *ch_name; /* Channel name */ size_t ch_namelen; /* Length of channel name buffer */ kmutex_t ch_mutex; /* To protect this structure */ evch_eventq_t *ch_queue; /* Publisher event queue */ evch_dlist_t ch_subscr; /* List of subscr. data (evch_subd_t) */ uint32_t ch_bindings; /* No of bindings to this channel */ int ch_maxbinds; /* Maximum number of binds */ uid_t ch_uid; /* Creators effective user id */ gid_t ch_gid; /* Creators effective group id */ kmutex_t ch_pubmx; /* Mutex for ch_pubcv and ch_nevents */ kcondvar_t ch_pubcv; /* To set publisher to sleep */ uint32_t ch_nevents; /* Current number of events */ uint32_t ch_maxev; /* Maximum number of events */ int ch_maxsubscr; /* Maximum number of subscriptions */ int ch_holdpend; /* Hold pending events mode if != 0 */ time_t ch_ctime; /* Channel creation time */ nvlist_t *ch_propnvl; /* Channel properties nvlist */ int64_t ch_propnvlgen; /* Properties generation number */ } evch_chan_t; /* * Channel binding structure. Allocated per binding to a channel. Protected * by locking the channel structure */ typedef struct { evch_chan_t *bd_channel; evch_subd_t *bd_sublst; /* chain of all subscriptions */ } evch_bind_t; /* * Structure to keep a snapshot of all events of a channel */ typedef struct { evch_eventq_t *sn_queue; /* Event queue with snapshot of ev's */ sysevent_impl_t *sn_nxtev; /* Pointer to find next event */ } evchanq_t; /* Project private interfaces */ extern evchan_t *evch_usrchanopen(const char *name, uint32_t flags, int *err); extern void evch_usrchanclose(evchan_t *cbp); extern sysevent_impl_t *evch_usrallocev(size_t evsize, uint32_t flags); extern void evch_usrfreeev(sysevent_impl_t *ev); extern int evch_usrpostevent(evchan_t *bp, sysevent_impl_t *ev, uint32_t flags); extern int evch_usrsubscribe(evchan_t *bp, const char *sid, const char *class, int d, uint32_t flags); extern int evch_usrcontrol_set(evchan_t *bp, int cmd, uint32_t value); extern int evch_usrcontrol_get(evchan_t *bp, int cmd, uint32_t *value); extern void evch_usrunsubscribe(evchan_t *bp, const char *subid, uint32_t flag); extern int evch_usrgetchnames(char *buf, size_t size); extern int evch_usrgetchdata(char *chname, void *buf, size_t size); extern void evch_usrsetpropnvl(evchan_t *bp, nvlist_t *nvl); extern int evch_usrgetpropnvl(evchan_t *bp, nvlist_t **nvlp, int64_t *genp); extern void sysevent_evc_init(); extern void sysevent_evc_thrinit(); extern evchanq_t *sysevent_evc_walk_init(evchan_t *, char *); extern sysevent_t *sysevent_evc_walk_step(evchanq_t *); extern void sysevent_evc_walk_fini(evchanq_t *); extern char *sysevent_evc_event_attr(sysevent_t *, size_t *); #endif /* _KERNEL */ /* * Structures and limits to deliver channel data to syseventadm */ #define EVCH_MAX_DATA_SIZE (1024 * 1024) typedef struct { uint32_t sb_nextoff; /* Offset to next subscr info struct */ uint32_t sb_stroff; /* Offset to strings */ uint32_t sb_clnamoff; /* Offset of class in sb_strings */ uint32_t sb_pid; /* Subscriber process id */ uint32_t sb_nevents; /* Current no of event in sub q */ uint32_t sb_evhwm; /* High watermark of sub q */ uint32_t sb_persist; /* != 0 if subscription persists */ uint32_t sb_status; /* != 0 if subscription is inactive */ uint32_t sb_active; /* > 0 if subscription is in use */ uint32_t sb_dump; /* != 0 if sub will be dumped */ char sb_strings[1]; /* String space for subid and class */ } sev_subinfo_t; typedef struct { uint32_t cd_version; /* Version of this structure */ uint32_t cd_suboffs; /* Offset of subscriber info struct */ uint64_t cd_ctime; /* Creation time */ uint32_t cd_uid; /* User id */ uint32_t cd_gid; /* Owner group id */ uint32_t cd_perms; /* Permission bits */ uint32_t cd_maxev; /* Max number of events */ uint32_t cd_evhwm; /* High watermark of main event queue */ uint32_t cd_nevents; /* current no of events in main ev q */ uint32_t cd_maxsub; /* Max number of subscriptions */ uint32_t cd_nsub; /* Current number of subscriptions */ uint32_t cd_maxbinds; /* Max number of binds */ uint32_t cd_nbinds; /* Current number of binds */ uint32_t cd_holdpend; /* != 0 when HOLDPEND mode is set */ uint32_t cd_limev; /* Limit of events per channel */ sev_subinfo_t cd_subinfo[1]; /* Per subscriber data */ } sev_chinfo_t; /* * Project private flags for sysevent_evc_subscribe. Bits 0 to 7 are reserved * for the consolidation private interface, so we must use bits 8-15 here. */ #define EVCH_SUB_DUMP (0x01 << 8) /* * Permission flags */ #define EVCH_PUB 0x0004 /* wants to publish events */ #define EVCH_SUB 0x0008 /* wants to subscribe to channel */ #define EVCH_SUBU 0x0001 /* Subscribing allowed for uid */ #define EVCH_PUBU 0x0002 /* Publishing allowed for uid */ #define EVCH_PSUSR 0x0003 /* EVCH_SUBU + EVCH_PUBU */ #define EVCH_SUBG 0x0004 /* Subscribing allowed for gid */ #define EVCH_PUBG 0x0008 /* Publishing allowed for gid */ #define EVCH_PSGRP 0x000C /* EVCH_SUBG + EVCH_PUBG */ #define EVCH_SUBO 0x0010 /* Subscribing allowed to all users */ #define EVCH_PUBO 0x0020 /* Publishing allowed to all users */ #define EVCH_PSOTH 0x0030 /* EVCH_SUBO + EVCH_PUBO */ #define EVCH_PSALL 0x003f /* Mask of all permission bits */ /* * Sysevent driver ioctls */ #define SEV_BASE 0x53455600 #define SEV_PUBLISH SEV_BASE | 0x01 #define SEV_CHAN_OPEN SEV_BASE | 0x02 #define SEV_CHAN_CONTROL SEV_BASE | 0x03 #define SEV_SUBSCRIBE SEV_BASE | 0x04 #define SEV_UNSUBSCRIBE SEV_BASE | 0x05 #define SEV_CHANNAMES SEV_BASE | 0x06 #define SEV_CHANDATA SEV_BASE | 0x07 #define SEV_SETPROPNVL SEV_BASE | 0x08 #define SEV_GETPROPNVL SEV_BASE | 0x09 #define DEVSYSEVENT "/dev/sysevent" #define DEVICESYSEVENT "/devices/pseudo/sysevent@0:sysevent" /* * Maximum allowed binding handles * It's a limit required by bitmap algorithm design (see sys/bitmap.h). * Use pack(4) to make sizeof structs be the same on x86 and amd64. */ #define SYSEVENT_MINOR_MAX SHRT_MAX #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 #pragma pack(4) #endif /* copyin/copyout data */ typedef struct box { uint64_t name; /* pointer to something */ uint32_t len; } sev_box_t; typedef struct bind_args { sev_box_t chan_name; uint32_t flags; } sev_bind_args_t; typedef struct control_args { uint32_t cmd; uint32_t value; } sev_control_args_t; typedef struct publish_args { sev_box_t ev; uint32_t flags; } sev_publish_args_t; typedef struct subscribe_args { sev_box_t sid; sev_box_t class_info; int door_desc; uint32_t flags; } sev_subscribe_args_t; typedef struct unsubscribe_args { sev_box_t sid; } sev_unsubscribe_args_t; typedef struct chandata { sev_box_t in_data; sev_box_t out_data; } sev_chandata_args_t; typedef struct propnvl_args { sev_box_t packednvl; /* input and output */ int64_t generation; /* output on get operation */ } sev_propnvl_args_t; #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 #pragma pack() #endif #ifdef __cplusplus } #endif #endif /* _SYS_SYSEVENT_IMPL_H */