130588217SMike Christensen /* 230588217SMike Christensen * CDDL HEADER START 330588217SMike Christensen * 430588217SMike Christensen * The contents of this file are subject to the terms of the 530588217SMike Christensen * Common Development and Distribution License (the "License"). 630588217SMike Christensen * You may not use this file except in compliance with the License. 730588217SMike Christensen * 830588217SMike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 930588217SMike Christensen * or http://www.opensolaris.org/os/licensing. 1030588217SMike Christensen * See the License for the specific language governing permissions 1130588217SMike Christensen * and limitations under the License. 1230588217SMike Christensen * 1330588217SMike Christensen * When distributing Covered Code, include this CDDL HEADER in each 1430588217SMike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1530588217SMike Christensen * If applicable, add the following below this CDDL HEADER, with the 1630588217SMike Christensen * fields enclosed by brackets "[]" replaced with your own identifying 1730588217SMike Christensen * information: Portions Copyright [yyyy] [name of copyright owner] 1830588217SMike Christensen * 1930588217SMike Christensen * CDDL HEADER END 2030588217SMike Christensen */ 2130588217SMike Christensen /* 22*49b225e1SGavin Maltby * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2330588217SMike Christensen * Use is subject to license terms. 2430588217SMike Christensen */ 2530588217SMike Christensen 2630588217SMike Christensen #include <stdio.h> 2730588217SMike Christensen #include <fcntl.h> 2830588217SMike Christensen #include <unistd.h> 2930588217SMike Christensen #include <stdlib.h> 3030588217SMike Christensen #include <strings.h> 3130588217SMike Christensen #include <errno.h> 3230588217SMike Christensen #include <sys/types.h> 3330588217SMike Christensen #include <sys/sysevent.h> 3430588217SMike Christensen #include <libsysevent.h> 3530588217SMike Christensen #include <sys/vlds.h> 3630588217SMike Christensen #include "libds.h" 3730588217SMike Christensen 3830588217SMike Christensen #define PTRTOUINT64(ptr) ((uint64_t)((uintptr_t)(ptr))) 3930588217SMike Christensen static char vlds_device[] = 4030588217SMike Christensen "/devices/virtual-devices@100/channel-devices@200/" 4130588217SMike Christensen "virtual-domain-service@0:vlds"; 4230588217SMike Christensen 4330588217SMike Christensen typedef struct dslibentry { 4430588217SMike Christensen ds_hdl_t dsl_hdl; 4530588217SMike Christensen uint32_t dsl_flags; 46ba9236fbSMike Christensen uint32_t dsl_tflags; 4730588217SMike Christensen char *dsl_service; 4830588217SMike Christensen ds_ops_t dsl_ops; 4930588217SMike Christensen } dslibentry_t; 5030588217SMike Christensen 51ba9236fbSMike Christensen /* dsl_tflags */ 52ba9236fbSMike Christensen #define DSL_ENTRY_INUSE 0x0001 /* handle is currently active */ 53ba9236fbSMike Christensen 5430588217SMike Christensen #define MIN_DSLIB_ENTRIES 64 5530588217SMike Christensen static dslibentry_t *dslibtab; 5630588217SMike Christensen static int ndslib; 5730588217SMike Christensen 5830588217SMike Christensen /* 5930588217SMike Christensen * Lock to protect the dslibtab table. We only need to protect this 6030588217SMike Christensen * table for those functions which actually look at or modify the table: 6130588217SMike Christensen * service registration (ds_svc_reg/ds_clnt_reg), service unregistration 6230588217SMike Christensen * (ds_hdl_unreg) or during callbacks (ds_recv) 6330588217SMike Christensen */ 6430588217SMike Christensen static mutex_t dslib_lock; 6530588217SMike Christensen 6630588217SMike Christensen static int ds_fd = -1; 6730588217SMike Christensen 6830588217SMike Christensen static char *ds_sid_name = "vlds"; 6930588217SMike Christensen 7030588217SMike Christensen static evchan_t *ds_evchan; 7130588217SMike Christensen 7230588217SMike Christensen /* 7330588217SMike Christensen * Static functions internal to dslib. 7430588217SMike Christensen */ 7530588217SMike Christensen static dslibentry_t *ds_hdl_to_dslibentry(ds_hdl_t hdl); 76ba9236fbSMike Christensen static dslibentry_t *ds_new_dslibentry(void); 77ba9236fbSMike Christensen static uint_t ds_service_count(char *service, boolean_t is_client); 7830588217SMike Christensen static dslibentry_t *ds_lookup_dslibentry(char *service, boolean_t is_client); 7930588217SMike Christensen static dslibentry_t *ds_register_dslibentry(ds_hdl_t hdl, char *service, 8030588217SMike Christensen boolean_t is_client); 8130588217SMike Christensen static void ds_free_dslibentry(dslibentry_t *dsp, int force_unreg); 8230588217SMike Christensen static int ds_recv(sysevent_t *sep, void *arg); 8330588217SMike Christensen static void ds_string_arg(vlds_string_t *dsp, char *str); 8430588217SMike Christensen static int ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags); 8530588217SMike Christensen 8630588217SMike Christensen static dslibentry_t * 8730588217SMike Christensen ds_hdl_to_dslibentry(ds_hdl_t hdl) 8830588217SMike Christensen { 8930588217SMike Christensen int i; 9030588217SMike Christensen dslibentry_t *dsp; 9130588217SMike Christensen 9230588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 9330588217SMike Christensen if (hdl == dsp->dsl_hdl) 9430588217SMike Christensen return (dsp); 9530588217SMike Christensen } 9630588217SMike Christensen return (NULL); 9730588217SMike Christensen } 9830588217SMike Christensen 9930588217SMike Christensen static dslibentry_t * 10030588217SMike Christensen ds_new_dslibentry(void) 10130588217SMike Christensen { 10230588217SMike Christensen int newndslib; 10330588217SMike Christensen dslibentry_t *dsp; 10430588217SMike Christensen 10530588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(NULL)) != NULL) 10630588217SMike Christensen return (dsp); 10730588217SMike Christensen 10830588217SMike Christensen /* double the size */ 10930588217SMike Christensen newndslib = ndslib << 1; 11030588217SMike Christensen if ((dslibtab = realloc(dslibtab, newndslib * sizeof (dslibentry_t))) 11130588217SMike Christensen == NULL) 11230588217SMike Christensen return (NULL); 11330588217SMike Christensen dsp = &dslibtab[ndslib]; 11430588217SMike Christensen (void) memset(dsp, 0, (newndslib - ndslib) * sizeof (dslibentry_t)); 11530588217SMike Christensen ndslib = newndslib; 11630588217SMike Christensen return (dsp); 11730588217SMike Christensen } 11830588217SMike Christensen 119ba9236fbSMike Christensen static uint_t 120ba9236fbSMike Christensen ds_service_count(char *service, boolean_t is_client) 121ba9236fbSMike Christensen { 122ba9236fbSMike Christensen int i; 123ba9236fbSMike Christensen dslibentry_t *dsp; 124ba9236fbSMike Christensen uint_t is_client_flag = is_client ? VLDS_REG_CLIENT : 0; 125ba9236fbSMike Christensen uint_t count = 0; 126ba9236fbSMike Christensen 127ba9236fbSMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 128ba9236fbSMike Christensen if (dsp->dsl_hdl != NULL && 129ba9236fbSMike Christensen strcmp(dsp->dsl_service, service) == 0 && 130ba9236fbSMike Christensen (dsp->dsl_flags & VLDS_REG_CLIENT) == is_client_flag) { 131ba9236fbSMike Christensen count++; 132ba9236fbSMike Christensen } 133ba9236fbSMike Christensen } 134ba9236fbSMike Christensen return (count); 135ba9236fbSMike Christensen } 136ba9236fbSMike Christensen 13730588217SMike Christensen static dslibentry_t * 13830588217SMike Christensen ds_lookup_dslibentry(char *service, boolean_t is_client) 13930588217SMike Christensen { 14030588217SMike Christensen int i; 14130588217SMike Christensen dslibentry_t *dsp; 14230588217SMike Christensen uint_t is_client_flag = is_client ? VLDS_REG_CLIENT : 0; 14330588217SMike Christensen 14430588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 14530588217SMike Christensen if (dsp->dsl_hdl != NULL && 14630588217SMike Christensen strcmp(dsp->dsl_service, service) == 0 && 14730588217SMike Christensen (dsp->dsl_flags & VLDS_REG_CLIENT) == is_client_flag) { 14830588217SMike Christensen return (dsp); 14930588217SMike Christensen } 15030588217SMike Christensen } 15130588217SMike Christensen return (NULL); 15230588217SMike Christensen } 15330588217SMike Christensen 15430588217SMike Christensen static dslibentry_t * 15530588217SMike Christensen ds_register_dslibentry(ds_hdl_t hdl, char *service, boolean_t is_client) 15630588217SMike Christensen { 15730588217SMike Christensen dslibentry_t *dsp, *orig_dsp; 15830588217SMike Christensen 159ba9236fbSMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 160ba9236fbSMike Christensen dsp->dsl_tflags |= DSL_ENTRY_INUSE; 16130588217SMike Christensen return (dsp); 162ba9236fbSMike Christensen } 16330588217SMike Christensen 16430588217SMike Christensen if ((orig_dsp = ds_lookup_dslibentry(service, is_client)) == NULL) { 16530588217SMike Christensen return (NULL); 16630588217SMike Christensen } 16730588217SMike Christensen 168ba9236fbSMike Christensen if ((orig_dsp->dsl_tflags & DSL_ENTRY_INUSE) == 0) { 169ba9236fbSMike Christensen /* use the original structure entry */ 170ba9236fbSMike Christensen orig_dsp->dsl_tflags |= DSL_ENTRY_INUSE; 171ba9236fbSMike Christensen orig_dsp->dsl_hdl = hdl; 172ba9236fbSMike Christensen return (orig_dsp); 173ba9236fbSMike Christensen } 17430588217SMike Christensen 17530588217SMike Christensen /* allocate a new structure entry */ 17630588217SMike Christensen if ((dsp = ds_new_dslibentry()) == NULL) 17730588217SMike Christensen return (NULL); 178ba9236fbSMike Christensen 17930588217SMike Christensen *dsp = *orig_dsp; 18030588217SMike Christensen dsp->dsl_service = strdup(orig_dsp->dsl_service); 18130588217SMike Christensen dsp->dsl_hdl = hdl; 18230588217SMike Christensen return (dsp); 18330588217SMike Christensen } 18430588217SMike Christensen 18530588217SMike Christensen /* 18630588217SMike Christensen * Want to leave an entry in the dslib table even though all the 18730588217SMike Christensen * handles may have been unregistered for it. 18830588217SMike Christensen */ 18930588217SMike Christensen static void 19030588217SMike Christensen ds_free_dslibentry(dslibentry_t *dsp, int force_unreg) 19130588217SMike Christensen { 19230588217SMike Christensen uint_t nhdls; 19330588217SMike Christensen 19430588217SMike Christensen /* 195ba9236fbSMike Christensen * Find out if we have 1 or 2 or more handles for the given 196ba9236fbSMike Christensen * service. Having one implies that we want to leave the entry 197ba9236fbSMike Christensen * intact but marked as not in use unless this is a ds_unreg_hdl 19830588217SMike Christensen * (force_unreg is true). 19930588217SMike Christensen */ 200ba9236fbSMike Christensen nhdls = ds_service_count(dsp->dsl_service, 201ba9236fbSMike Christensen (dsp->dsl_flags & VLDS_REG_CLIENT) != 0); 20230588217SMike Christensen 203ba9236fbSMike Christensen if ((nhdls == 1 && force_unreg) || nhdls >= 2) { 20430588217SMike Christensen dsp->dsl_hdl = NULL; 20530588217SMike Christensen if (dsp->dsl_service) { 20630588217SMike Christensen free(dsp->dsl_service); 20730588217SMike Christensen } 20830588217SMike Christensen (void) memset(dsp, 0, sizeof (dslibentry_t)); 209ba9236fbSMike Christensen } else if (nhdls == 1) { 210ba9236fbSMike Christensen dsp->dsl_tflags &= ~DSL_ENTRY_INUSE; 21130588217SMike Christensen } 21230588217SMike Christensen } 21330588217SMike Christensen 21430588217SMike Christensen /*ARGSUSED*/ 21530588217SMike Christensen static int 21630588217SMike Christensen ds_recv(sysevent_t *sep, void *arg) 21730588217SMike Christensen { 21830588217SMike Christensen nvlist_t *nvl; 21930588217SMike Christensen uint64_t hdl; 22030588217SMike Christensen ds_ver_t ver; 22130588217SMike Christensen ds_domain_hdl_t dhdl; 22230588217SMike Christensen uchar_t *bufp; 22330588217SMike Christensen boolean_t is_client; 22430588217SMike Christensen uint_t buflen; 22530588217SMike Christensen char *subclass; 22630588217SMike Christensen char *servicep; 22730588217SMike Christensen dslibentry_t *dsp; 22830588217SMike Christensen ds_cb_arg_t cb_arg; 22930588217SMike Christensen 23030588217SMike Christensen subclass = sysevent_get_subclass_name(sep); 23130588217SMike Christensen if (sysevent_get_attr_list(sep, &nvl) != 0) { 23230588217SMike Christensen return (0); 23330588217SMike Christensen } 23430588217SMike Christensen 23530588217SMike Christensen if (nvlist_lookup_uint64(nvl, VLDS_HDL, &hdl) == 0) { 23630588217SMike Christensen if (strcmp(subclass, ESC_VLDS_REGISTER) == 0) { 23730588217SMike Christensen void (*reg_cb)(ds_hdl_t, ds_cb_arg_t, ds_ver_t *, 23830588217SMike Christensen ds_domain_hdl_t) = NULL; 23930588217SMike Christensen 24030588217SMike Christensen if (nvlist_lookup_string(nvl, VLDS_SERVICE_ID, 24130588217SMike Christensen &servicep) == 0 && 24230588217SMike Christensen nvlist_lookup_boolean_value(nvl, VLDS_ISCLIENT, 24330588217SMike Christensen &is_client) == 0) { 24430588217SMike Christensen (void) mutex_lock(&dslib_lock); 24530588217SMike Christensen if ((dsp = ds_register_dslibentry(hdl, 24630588217SMike Christensen servicep, is_client)) != NULL) { 24730588217SMike Christensen reg_cb = dsp->dsl_ops.ds_reg_cb; 24830588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 24930588217SMike Christensen } 25030588217SMike Christensen (void) mutex_unlock(&dslib_lock); 25130588217SMike Christensen if (reg_cb != NULL && 25230588217SMike Christensen nvlist_lookup_uint64(nvl, VLDS_DOMAIN_HDL, 25330588217SMike Christensen &dhdl) == 0 && 25430588217SMike Christensen nvlist_lookup_uint16(nvl, VLDS_VER_MAJOR, 25530588217SMike Christensen &ver.major) == 0 && 25630588217SMike Christensen nvlist_lookup_uint16(nvl, VLDS_VER_MINOR, 25730588217SMike Christensen &ver.minor) == 0) { 25830588217SMike Christensen (reg_cb)((ds_hdl_t)hdl, cb_arg, &ver, 25930588217SMike Christensen dhdl); 26030588217SMike Christensen } 26130588217SMike Christensen } 26230588217SMike Christensen } else if (strcmp(subclass, ESC_VLDS_UNREGISTER) == 0) { 26330588217SMike Christensen void (*unreg_cb)(ds_hdl_t, ds_cb_arg_t) = NULL; 26430588217SMike Christensen 26530588217SMike Christensen (void) mutex_lock(&dslib_lock); 26630588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 26730588217SMike Christensen unreg_cb = dsp->dsl_ops.ds_unreg_cb; 26830588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 26930588217SMike Christensen ds_free_dslibentry(dsp, 0); 27030588217SMike Christensen } 27130588217SMike Christensen (void) mutex_unlock(&dslib_lock); 27230588217SMike Christensen if (unreg_cb != NULL) { 27330588217SMike Christensen (unreg_cb)((ds_hdl_t)hdl, cb_arg); 27430588217SMike Christensen } 27530588217SMike Christensen } else if (strcmp(subclass, ESC_VLDS_DATA) == 0) { 27630588217SMike Christensen void (*data_cb)(ds_hdl_t, ds_cb_arg_t, void *, 27730588217SMike Christensen size_t) = NULL; 27830588217SMike Christensen 27930588217SMike Christensen (void) mutex_lock(&dslib_lock); 28030588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 28130588217SMike Christensen data_cb = dsp->dsl_ops.ds_data_cb; 28230588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 28330588217SMike Christensen } 28430588217SMike Christensen (void) mutex_unlock(&dslib_lock); 28530588217SMike Christensen if (data_cb != NULL && 28630588217SMike Christensen nvlist_lookup_byte_array(nvl, VLDS_DATA, &bufp, 28730588217SMike Christensen &buflen) == 0) { 28830588217SMike Christensen (data_cb)((ds_hdl_t)hdl, cb_arg, bufp, buflen); 28930588217SMike Christensen } 29030588217SMike Christensen } 29130588217SMike Christensen } 29230588217SMike Christensen nvlist_free(nvl); 29330588217SMike Christensen return (0); 29430588217SMike Christensen } 29530588217SMike Christensen 29630588217SMike Christensen static void 29730588217SMike Christensen ds_string_arg(vlds_string_t *dsp, char *str) 29830588217SMike Christensen { 29930588217SMike Christensen if (str == NULL) { 30030588217SMike Christensen dsp->vlds_strp = NULL; 30130588217SMike Christensen dsp->vlds_strlen = 0; 30230588217SMike Christensen } else { 30330588217SMike Christensen dsp->vlds_strp = PTRTOUINT64(str); 30430588217SMike Christensen dsp->vlds_strlen = strlen(str) + 1; 30530588217SMike Christensen } 30630588217SMike Christensen } 30730588217SMike Christensen 30830588217SMike Christensen static int 30930588217SMike Christensen ds_init_sysev(void) 31030588217SMike Christensen { 31130588217SMike Christensen char evchan_name[MAX_CHNAME_LEN]; 31230588217SMike Christensen 31330588217SMike Christensen (void) sprintf(evchan_name, VLDS_SYSEV_CHAN_FMT, (int)getpid()); 31430588217SMike Christensen if (sysevent_evc_bind(evchan_name, &ds_evchan, 0) != 0) { 31530588217SMike Christensen return (errno); 31630588217SMike Christensen } 31730588217SMike Christensen if (sysevent_evc_subscribe(ds_evchan, ds_sid_name, EC_VLDS, 31830588217SMike Christensen ds_recv, NULL, 0) != 0) { 319*49b225e1SGavin Maltby (void) sysevent_evc_unbind(ds_evchan); 32030588217SMike Christensen ds_evchan = NULL; 32130588217SMike Christensen return (errno); 32230588217SMike Christensen } 32330588217SMike Christensen return (0); 32430588217SMike Christensen } 32530588217SMike Christensen 32630588217SMike Christensen int 32730588217SMike Christensen ds_init(void) 32830588217SMike Christensen { 32930588217SMike Christensen if (ds_fd >= 0) 33030588217SMike Christensen return (0); 33130588217SMike Christensen 33230588217SMike Christensen if ((ds_fd = open(vlds_device, 0)) < 0) 33330588217SMike Christensen return (errno); 33430588217SMike Christensen 33530588217SMike Christensen if (dslibtab == NULL) { 336ba9236fbSMike Christensen dslibtab = malloc(sizeof (dslibentry_t) * MIN_DSLIB_ENTRIES); 337ba9236fbSMike Christensen if (dslibtab == NULL) 33830588217SMike Christensen return (errno = ENOMEM); 33930588217SMike Christensen ndslib = MIN_DSLIB_ENTRIES; 34030588217SMike Christensen (void) memset(dslibtab, 0, sizeof (dslibentry_t) * ndslib); 34130588217SMike Christensen } 34230588217SMike Christensen 34330588217SMike Christensen (void) mutex_init(&dslib_lock, USYNC_THREAD, NULL); 34430588217SMike Christensen return (0); 34530588217SMike Christensen } 34630588217SMike Christensen 34730588217SMike Christensen static int 34830588217SMike Christensen ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags) 34930588217SMike Christensen { 35030588217SMike Christensen dslibentry_t *dsp; 35130588217SMike Christensen vlds_svc_reg_arg_t vlds_arg; 35230588217SMike Christensen vlds_cap_t vlds_cap; 35330588217SMike Christensen vlds_ver_t vlds_vers[VLDS_MAX_VERS]; 35430588217SMike Christensen uint64_t hdl_arg; 35530588217SMike Christensen ds_hdl_t hdl; 35630588217SMike Christensen uint_t nhdls; 35730588217SMike Christensen int i; 35830588217SMike Christensen 35930588217SMike Christensen if (cap == NULL || ops == NULL || cap->svc_id == NULL || 36030588217SMike Christensen cap->vers == NULL || (flags & (~VLDS_REG_CLIENT)) != 0) { 36130588217SMike Christensen return (errno = EINVAL); 36230588217SMike Christensen } 36330588217SMike Christensen 36430588217SMike Christensen if (cap->nvers > VLDS_MAX_VERS) { 36530588217SMike Christensen return (errno = EINVAL); 36630588217SMike Christensen } 36730588217SMike Christensen 36830588217SMike Christensen if (ds_fd < 0 && (errno = ds_init()) != 0) { 36930588217SMike Christensen return (errno); 37030588217SMike Christensen } 37130588217SMike Christensen 37230588217SMike Christensen if (ds_hdl_lookup(cap->svc_id, (flags & VLDS_REG_CLIENT), NULL, 1, 37330588217SMike Christensen &nhdls) == 0 && nhdls == 1) { 37430588217SMike Christensen return (errno = EALREADY); 37530588217SMike Christensen } 37630588217SMike Christensen 37730588217SMike Christensen (void) mutex_lock(&dslib_lock); 37830588217SMike Christensen if ((dsp = ds_new_dslibentry()) == NULL) { 37930588217SMike Christensen (void) mutex_unlock(&dslib_lock); 38030588217SMike Christensen return (errno = ENOMEM); 38130588217SMike Christensen } 38230588217SMike Christensen 38330588217SMike Christensen /* Setup device driver capability structure. */ 38430588217SMike Christensen 38530588217SMike Christensen /* service string */ 38630588217SMike Christensen ds_string_arg(&vlds_cap.vlds_service, cap->svc_id); 38730588217SMike Christensen 38830588217SMike Christensen /* version array */ 38930588217SMike Christensen for (i = 0; i < cap->nvers; i++) { 39030588217SMike Christensen vlds_vers[i].vlds_major = cap->vers[i].major; 39130588217SMike Christensen vlds_vers[i].vlds_minor = cap->vers[i].minor; 39230588217SMike Christensen } 39330588217SMike Christensen vlds_cap.vlds_versp = PTRTOUINT64(vlds_vers); 39430588217SMike Christensen vlds_cap.vlds_nver = cap->nvers; 39530588217SMike Christensen 39630588217SMike Christensen /* 39730588217SMike Christensen * Format args for VLDS_SVC_REG ioctl. 39830588217SMike Christensen */ 39930588217SMike Christensen 40030588217SMike Christensen vlds_arg.vlds_capp = PTRTOUINT64(&vlds_cap); 40130588217SMike Christensen 40230588217SMike Christensen /* op flags */ 40330588217SMike Christensen if (ops->ds_reg_cb != NULL) 40430588217SMike Christensen flags |= VLDS_REGCB_VALID; 40530588217SMike Christensen if (ops->ds_unreg_cb != NULL) 40630588217SMike Christensen flags |= VLDS_UNREGCB_VALID; 40730588217SMike Christensen if (ops->ds_data_cb != NULL) 40830588217SMike Christensen flags |= VLDS_DATACB_VALID; 40930588217SMike Christensen vlds_arg.vlds_reg_flags = flags; 41030588217SMike Christensen 41130588217SMike Christensen /* returned handle */ 41230588217SMike Christensen vlds_arg.vlds_hdlp = PTRTOUINT64(&hdl_arg); 41330588217SMike Christensen 41430588217SMike Christensen if (ioctl(ds_fd, VLDS_SVC_REG, &vlds_arg) < 0) { 41530588217SMike Christensen (void) mutex_unlock(&dslib_lock); 41630588217SMike Christensen return (errno); 41730588217SMike Christensen } 41830588217SMike Christensen 41930588217SMike Christensen /* 42030588217SMike Christensen * Setup user callback sysevent channel. 42130588217SMike Christensen */ 42230588217SMike Christensen if ((flags & VLDS_ANYCB_VALID) != 0 && ds_evchan == NULL && 42330588217SMike Christensen ds_init_sysev() != 0) { 42430588217SMike Christensen (void) mutex_unlock(&dslib_lock); 42530588217SMike Christensen (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg); 42630588217SMike Christensen return (errno); 42730588217SMike Christensen } 42830588217SMike Christensen 42930588217SMike Christensen hdl = hdl_arg; 43030588217SMike Christensen 43130588217SMike Christensen /* 43230588217SMike Christensen * Set entry values in dslibtab. 43330588217SMike Christensen */ 43430588217SMike Christensen dsp->dsl_hdl = hdl; 43530588217SMike Christensen dsp->dsl_flags = flags; 436ba9236fbSMike Christensen dsp->dsl_tflags = 0; 43730588217SMike Christensen dsp->dsl_service = strdup(cap->svc_id); 43830588217SMike Christensen dsp->dsl_ops = *ops; 43930588217SMike Christensen (void) mutex_unlock(&dslib_lock); 44030588217SMike Christensen return (0); 44130588217SMike Christensen } 44230588217SMike Christensen 44330588217SMike Christensen /* 44430588217SMike Christensen * Registers a service provider. Kicks off the handshake with other 44530588217SMike Christensen * domain(s) to announce servce. Callback events are as described above. 44630588217SMike Christensen */ 44730588217SMike Christensen int 44830588217SMike Christensen ds_svc_reg(ds_capability_t *cap, ds_ops_t *ops) 44930588217SMike Christensen { 45030588217SMike Christensen return (ds_register(cap, ops, 0)); 45130588217SMike Christensen } 45230588217SMike Christensen 45330588217SMike Christensen /* 45430588217SMike Christensen * Registers interest in a service from a specific domain. When that 45530588217SMike Christensen * service is registered, the register callback is invoked. When that 45630588217SMike Christensen * service is unregistered, the unregister callback is invoked. When 45730588217SMike Christensen * data is received, the receive data callback is invoked. 45830588217SMike Christensen */ 45930588217SMike Christensen int 46030588217SMike Christensen ds_clnt_reg(ds_capability_t *cap, ds_ops_t *ops) 46130588217SMike Christensen { 46230588217SMike Christensen return (ds_register(cap, ops, VLDS_REG_CLIENT)); 46330588217SMike Christensen } 46430588217SMike Christensen 46530588217SMike Christensen /* 46630588217SMike Christensen * Given a service name and type, returns the existing handle(s), if 46730588217SMike Christensen * one or more exist. This could be used to poll for the connection being 46830588217SMike Christensen * registered or unregistered, rather than using the register/unregister 46930588217SMike Christensen * callbacks. 47030588217SMike Christensen */ 47130588217SMike Christensen int 47230588217SMike Christensen ds_hdl_lookup(char *service, boolean_t is_client, ds_hdl_t *hdlsp, 47330588217SMike Christensen uint_t maxhdls, uint_t *nhdlsp) 47430588217SMike Christensen { 47530588217SMike Christensen vlds_hdl_lookup_arg_t vlds_arg; 47630588217SMike Christensen uint64_t nhdls_arg; 47730588217SMike Christensen 47830588217SMike Christensen errno = 0; 47930588217SMike Christensen if (ds_fd < 0) { 48030588217SMike Christensen return (errno = EBADF); 48130588217SMike Christensen } 48230588217SMike Christensen 48330588217SMike Christensen if (service == NULL) { 48430588217SMike Christensen return (errno = EINVAL); 48530588217SMike Christensen } 48630588217SMike Christensen 48730588217SMike Christensen ds_string_arg(&vlds_arg.vlds_service, service); 48830588217SMike Christensen vlds_arg.vlds_isclient = is_client ? VLDS_REG_CLIENT : 0; 48930588217SMike Christensen vlds_arg.vlds_hdlsp = PTRTOUINT64(hdlsp); 49030588217SMike Christensen vlds_arg.vlds_maxhdls = maxhdls; 49130588217SMike Christensen vlds_arg.vlds_nhdlsp = PTRTOUINT64(&nhdls_arg); 49230588217SMike Christensen 49330588217SMike Christensen if (ioctl(ds_fd, VLDS_HDL_LOOKUP, &vlds_arg) < 0) { 49430588217SMike Christensen return (errno); 49530588217SMike Christensen } 49630588217SMike Christensen 49730588217SMike Christensen *nhdlsp = nhdls_arg; 49830588217SMike Christensen return (0); 49930588217SMike Christensen } 50030588217SMike Christensen 50130588217SMike Christensen /* 50230588217SMike Christensen * Given a handle, return its associated domain. 50330588217SMike Christensen */ 50430588217SMike Christensen int 50530588217SMike Christensen ds_domain_lookup(ds_hdl_t hdl, ds_domain_hdl_t *dhdlp) 50630588217SMike Christensen { 50730588217SMike Christensen vlds_dmn_lookup_arg_t vlds_arg; 50830588217SMike Christensen uint64_t dhdl_arg; 50930588217SMike Christensen 51030588217SMike Christensen if (ds_fd < 0) { 51130588217SMike Christensen return (errno = EBADF); 51230588217SMike Christensen } 51330588217SMike Christensen 51430588217SMike Christensen vlds_arg.vlds_hdl = hdl; 51530588217SMike Christensen vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg); 51630588217SMike Christensen 51730588217SMike Christensen if (ioctl(ds_fd, VLDS_DMN_LOOKUP, &vlds_arg) < 0) { 51830588217SMike Christensen return (errno); 51930588217SMike Christensen } 52030588217SMike Christensen 52130588217SMike Christensen if (dhdlp) { 52230588217SMike Christensen *dhdlp = dhdl_arg; 52330588217SMike Christensen } 52430588217SMike Christensen 52530588217SMike Christensen return (0); 52630588217SMike Christensen } 52730588217SMike Christensen 52830588217SMike Christensen /* 52930588217SMike Christensen * Unregisters either a service or an interest in that service 53030588217SMike Christensen * indicated by the supplied handle. 53130588217SMike Christensen */ 53230588217SMike Christensen int 53330588217SMike Christensen ds_unreg_hdl(ds_hdl_t hdl) 53430588217SMike Christensen { 53530588217SMike Christensen dslibentry_t *dsp; 53630588217SMike Christensen vlds_unreg_hdl_arg_t vlds_arg; 53730588217SMike Christensen 53830588217SMike Christensen (void) mutex_lock(&dslib_lock); 53930588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 54030588217SMike Christensen ds_free_dslibentry(dsp, 1); 54130588217SMike Christensen } 54230588217SMike Christensen (void) mutex_unlock(&dslib_lock); 54330588217SMike Christensen 54430588217SMike Christensen if (ds_fd >= 0) { 54530588217SMike Christensen vlds_arg.vlds_hdl = hdl; 54630588217SMike Christensen (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg); 54730588217SMike Christensen } 54830588217SMike Christensen 54930588217SMike Christensen return (0); 55030588217SMike Christensen } 55130588217SMike Christensen 55230588217SMike Christensen /* 55330588217SMike Christensen * Send data to the appropriate service provider or client 55430588217SMike Christensen * indicated by the provided handle. The sender will block 55530588217SMike Christensen * until the message has been sent. There is no guarantee 55630588217SMike Christensen * that multiple calls to ds_send_msg by the same thread 55730588217SMike Christensen * will result in the data showing up at the receiver in 55830588217SMike Christensen * the same order as sent. If multiple messages are required, 55930588217SMike Christensen * it will be up to the sender and receiver to implement a 56030588217SMike Christensen * protocol. 56130588217SMike Christensen */ 56230588217SMike Christensen int 56330588217SMike Christensen ds_send_msg(ds_hdl_t hdl, void *buf, size_t buflen) 56430588217SMike Christensen { 56530588217SMike Christensen vlds_send_msg_arg_t vlds_arg; 56630588217SMike Christensen 56730588217SMike Christensen if (ds_fd < 0) { 56830588217SMike Christensen return (errno = EBADF); 56930588217SMike Christensen } 57030588217SMike Christensen 57130588217SMike Christensen vlds_arg.vlds_hdl = hdl; 57230588217SMike Christensen vlds_arg.vlds_bufp = PTRTOUINT64(buf); 57330588217SMike Christensen vlds_arg.vlds_buflen = buflen; 57430588217SMike Christensen 57530588217SMike Christensen if (ioctl(ds_fd, VLDS_SEND_MSG, &vlds_arg) < 0) { 57630588217SMike Christensen return (errno); 57730588217SMike Christensen } 57830588217SMike Christensen 57930588217SMike Christensen return (0); 58030588217SMike Christensen } 58130588217SMike Christensen 58230588217SMike Christensen /* 58330588217SMike Christensen * Receive data from the appropriate service provider or client 58430588217SMike Christensen * indicated by the provided handle. The sender will block 58530588217SMike Christensen * until a message has been received. 58630588217SMike Christensen */ 58730588217SMike Christensen int 58830588217SMike Christensen ds_recv_msg(ds_hdl_t hdl, void *buf, size_t buflen, size_t *msglen) 58930588217SMike Christensen { 59030588217SMike Christensen vlds_recv_msg_arg_t vlds_arg; 59130588217SMike Christensen uint64_t msglen_arg; 59230588217SMike Christensen 59330588217SMike Christensen if (ds_fd < 0) { 59430588217SMike Christensen return (errno = EBADF); 59530588217SMike Christensen } 59630588217SMike Christensen 59730588217SMike Christensen vlds_arg.vlds_hdl = hdl; 59830588217SMike Christensen vlds_arg.vlds_bufp = PTRTOUINT64(buf); 59930588217SMike Christensen vlds_arg.vlds_buflen = buflen; 60030588217SMike Christensen vlds_arg.vlds_msglenp = PTRTOUINT64(&msglen_arg); 60130588217SMike Christensen 60230588217SMike Christensen if (ioctl(ds_fd, VLDS_RECV_MSG, &vlds_arg) < 0) { 60330588217SMike Christensen if (errno == EFBIG && msglen) { 60430588217SMike Christensen *msglen = msglen_arg; 60530588217SMike Christensen } 60630588217SMike Christensen return (errno); 60730588217SMike Christensen } 60830588217SMike Christensen 60930588217SMike Christensen if (msglen) { 61030588217SMike Christensen *msglen = msglen_arg; 61130588217SMike Christensen } 61230588217SMike Christensen 61330588217SMike Christensen return (0); 61430588217SMike Christensen } 61530588217SMike Christensen 61630588217SMike Christensen int 61730588217SMike Christensen ds_isready(ds_hdl_t hdl, boolean_t *is_ready) 61830588217SMike Christensen { 61930588217SMike Christensen vlds_hdl_isready_arg_t vlds_arg; 62030588217SMike Christensen uint64_t is_ready_arg; 62130588217SMike Christensen 62230588217SMike Christensen if (ds_fd < 0) { 62330588217SMike Christensen return (errno = EBADF); 62430588217SMike Christensen } 62530588217SMike Christensen 62630588217SMike Christensen vlds_arg.vlds_hdl = hdl; 62730588217SMike Christensen vlds_arg.vlds_isreadyp = PTRTOUINT64(&is_ready_arg); 62830588217SMike Christensen 62930588217SMike Christensen if (ioctl(ds_fd, VLDS_HDL_ISREADY, &vlds_arg) < 0) { 63030588217SMike Christensen return (errno); 63130588217SMike Christensen } 63230588217SMike Christensen 63330588217SMike Christensen *is_ready = (is_ready_arg != 0); 63430588217SMike Christensen return (0); 63530588217SMike Christensen } 63630588217SMike Christensen 63730588217SMike Christensen /* 63830588217SMike Christensen * Given a domain name, return its associated domain handle. 63930588217SMike Christensen */ 64030588217SMike Christensen int 64130588217SMike Christensen ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp) 64230588217SMike Christensen { 64330588217SMike Christensen vlds_dom_nam2hdl_arg_t vlds_arg; 64430588217SMike Christensen uint64_t dhdl_arg; 64530588217SMike Christensen 64630588217SMike Christensen if (ds_fd < 0) { 64730588217SMike Christensen return (errno = EBADF); 64830588217SMike Christensen } 64930588217SMike Christensen 65030588217SMike Christensen ds_string_arg(&vlds_arg.vlds_domain_name, domain_name); 65130588217SMike Christensen vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg); 65230588217SMike Christensen 65330588217SMike Christensen if (ioctl(ds_fd, VLDS_DOM_NAM2HDL, &vlds_arg) < 0) { 65430588217SMike Christensen return (errno); 65530588217SMike Christensen } 65630588217SMike Christensen 65730588217SMike Christensen if (dhdlp) { 65830588217SMike Christensen *dhdlp = dhdl_arg; 65930588217SMike Christensen } 66030588217SMike Christensen 66130588217SMike Christensen return (0); 66230588217SMike Christensen } 66330588217SMike Christensen 66430588217SMike Christensen /* 66530588217SMike Christensen * Given a domain handle, return its associated domain name. 66630588217SMike Christensen */ 66730588217SMike Christensen int 66830588217SMike Christensen ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char *domain_name, uint_t maxnamlen) 66930588217SMike Christensen { 67030588217SMike Christensen vlds_dom_hdl2nam_arg_t vlds_arg; 67130588217SMike Christensen 67230588217SMike Christensen if (ds_fd < 0) { 67330588217SMike Christensen return (errno = EBADF); 67430588217SMike Christensen } 67530588217SMike Christensen 67630588217SMike Christensen vlds_arg.vlds_dhdl = dhdl; 67730588217SMike Christensen vlds_arg.vlds_domain_name.vlds_strp = PTRTOUINT64(domain_name); 67830588217SMike Christensen vlds_arg.vlds_domain_name.vlds_strlen = maxnamlen; 67930588217SMike Christensen 68030588217SMike Christensen if (ioctl(ds_fd, VLDS_DOM_HDL2NAM, &vlds_arg) < 0) { 68130588217SMike Christensen return (errno); 68230588217SMike Christensen } 68330588217SMike Christensen 68430588217SMike Christensen return (0); 68530588217SMike Christensen } 68630588217SMike Christensen 68730588217SMike Christensen void 68830588217SMike Christensen ds_unreg_svc(char *service, boolean_t is_client) 68930588217SMike Christensen { 69030588217SMike Christensen ds_hdl_t hdl; 69130588217SMike Christensen uint_t nhdls; 69230588217SMike Christensen 69330588217SMike Christensen while (ds_hdl_lookup(service, is_client, &hdl, 1, &nhdls) == 0 && 69430588217SMike Christensen nhdls == 1) { 69530588217SMike Christensen (void) ds_unreg_hdl(hdl); 69630588217SMike Christensen } 69730588217SMike Christensen } 69830588217SMike Christensen 69930588217SMike Christensen void 70030588217SMike Christensen ds_fini(void) 70130588217SMike Christensen { 70230588217SMike Christensen int i; 70330588217SMike Christensen dslibentry_t *dsp; 70430588217SMike Christensen 70530588217SMike Christensen if (ds_fd >= 0) { 70630588217SMike Christensen (void) close(ds_fd); 70730588217SMike Christensen ds_fd = -1; 70830588217SMike Christensen } 70930588217SMike Christensen if (ds_evchan) { 71030588217SMike Christensen (void) sysevent_evc_unsubscribe(ds_evchan, ds_sid_name); 71130588217SMike Christensen (void) sysevent_evc_unbind(ds_evchan); 71230588217SMike Christensen ds_evchan = NULL; 71330588217SMike Christensen } 71430588217SMike Christensen if (ndslib > 0) { 71530588217SMike Christensen (void) mutex_lock(&dslib_lock); 71630588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 71730588217SMike Christensen if (dsp->dsl_hdl == NULL) 71830588217SMike Christensen continue; 71930588217SMike Christensen if (dsp->dsl_service) { 72030588217SMike Christensen free(dsp->dsl_service); 72130588217SMike Christensen } 72230588217SMike Christensen } 72330588217SMike Christensen free(dslibtab); 72430588217SMike Christensen ndslib = 0; 72530588217SMike Christensen dslibtab = NULL; 72630588217SMike Christensen (void) mutex_unlock(&dslib_lock); 72730588217SMike Christensen (void) mutex_destroy(&dslib_lock); 72830588217SMike Christensen } 72930588217SMike Christensen } 730