1*30588217SMike Christensen /* 2*30588217SMike Christensen * CDDL HEADER START 3*30588217SMike Christensen * 4*30588217SMike Christensen * The contents of this file are subject to the terms of the 5*30588217SMike Christensen * Common Development and Distribution License (the "License"). 6*30588217SMike Christensen * You may not use this file except in compliance with the License. 7*30588217SMike Christensen * 8*30588217SMike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*30588217SMike Christensen * or http://www.opensolaris.org/os/licensing. 10*30588217SMike Christensen * See the License for the specific language governing permissions 11*30588217SMike Christensen * and limitations under the License. 12*30588217SMike Christensen * 13*30588217SMike Christensen * When distributing Covered Code, include this CDDL HEADER in each 14*30588217SMike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*30588217SMike Christensen * If applicable, add the following below this CDDL HEADER, with the 16*30588217SMike Christensen * fields enclosed by brackets "[]" replaced with your own identifying 17*30588217SMike Christensen * information: Portions Copyright [yyyy] [name of copyright owner] 18*30588217SMike Christensen * 19*30588217SMike Christensen * CDDL HEADER END 20*30588217SMike Christensen */ 21*30588217SMike Christensen /* 22*30588217SMike Christensen * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*30588217SMike Christensen * Use is subject to license terms. 24*30588217SMike Christensen */ 25*30588217SMike Christensen 26*30588217SMike Christensen #include <stdio.h> 27*30588217SMike Christensen #include <fcntl.h> 28*30588217SMike Christensen #include <unistd.h> 29*30588217SMike Christensen #include <stdlib.h> 30*30588217SMike Christensen #include <strings.h> 31*30588217SMike Christensen #include <errno.h> 32*30588217SMike Christensen #include <sys/types.h> 33*30588217SMike Christensen #include <sys/sysevent.h> 34*30588217SMike Christensen #include <libsysevent.h> 35*30588217SMike Christensen #include <sys/vlds.h> 36*30588217SMike Christensen #include "libds.h" 37*30588217SMike Christensen 38*30588217SMike Christensen #define PTRTOUINT64(ptr) ((uint64_t)((uintptr_t)(ptr))) 39*30588217SMike Christensen static char vlds_device[] = 40*30588217SMike Christensen "/devices/virtual-devices@100/channel-devices@200/" 41*30588217SMike Christensen "virtual-domain-service@0:vlds"; 42*30588217SMike Christensen 43*30588217SMike Christensen typedef struct dslibentry { 44*30588217SMike Christensen ds_hdl_t dsl_hdl; 45*30588217SMike Christensen uint32_t dsl_flags; 46*30588217SMike Christensen char *dsl_service; 47*30588217SMike Christensen ds_ops_t dsl_ops; 48*30588217SMike Christensen } dslibentry_t; 49*30588217SMike Christensen 50*30588217SMike Christensen #define MIN_DSLIB_ENTRIES 64 51*30588217SMike Christensen static dslibentry_t *dslibtab; 52*30588217SMike Christensen static int ndslib; 53*30588217SMike Christensen 54*30588217SMike Christensen /* 55*30588217SMike Christensen * Lock to protect the dslibtab table. We only need to protect this 56*30588217SMike Christensen * table for those functions which actually look at or modify the table: 57*30588217SMike Christensen * service registration (ds_svc_reg/ds_clnt_reg), service unregistration 58*30588217SMike Christensen * (ds_hdl_unreg) or during callbacks (ds_recv) 59*30588217SMike Christensen */ 60*30588217SMike Christensen static mutex_t dslib_lock; 61*30588217SMike Christensen 62*30588217SMike Christensen static int ds_fd = -1; 63*30588217SMike Christensen 64*30588217SMike Christensen static char *ds_sid_name = "vlds"; 65*30588217SMike Christensen 66*30588217SMike Christensen static evchan_t *ds_evchan; 67*30588217SMike Christensen 68*30588217SMike Christensen /* 69*30588217SMike Christensen * Static functions internal to dslib. 70*30588217SMike Christensen */ 71*30588217SMike Christensen static dslibentry_t *ds_hdl_to_dslibentry(ds_hdl_t hdl); 72*30588217SMike Christensen static dslibentry_t *ds_lookup_dslibentry(char *service, boolean_t is_client); 73*30588217SMike Christensen static dslibentry_t *ds_register_dslibentry(ds_hdl_t hdl, char *service, 74*30588217SMike Christensen boolean_t is_client); 75*30588217SMike Christensen static void ds_free_dslibentry(dslibentry_t *dsp, int force_unreg); 76*30588217SMike Christensen static int ds_recv(sysevent_t *sep, void *arg); 77*30588217SMike Christensen static void ds_string_arg(vlds_string_t *dsp, char *str); 78*30588217SMike Christensen static int ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags); 79*30588217SMike Christensen 80*30588217SMike Christensen static dslibentry_t * 81*30588217SMike Christensen ds_hdl_to_dslibentry(ds_hdl_t hdl) 82*30588217SMike Christensen { 83*30588217SMike Christensen int i; 84*30588217SMike Christensen dslibentry_t *dsp; 85*30588217SMike Christensen 86*30588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 87*30588217SMike Christensen if (hdl == dsp->dsl_hdl) 88*30588217SMike Christensen return (dsp); 89*30588217SMike Christensen } 90*30588217SMike Christensen return (NULL); 91*30588217SMike Christensen } 92*30588217SMike Christensen 93*30588217SMike Christensen static dslibentry_t * 94*30588217SMike Christensen ds_new_dslibentry(void) 95*30588217SMike Christensen { 96*30588217SMike Christensen int newndslib; 97*30588217SMike Christensen dslibentry_t *dsp; 98*30588217SMike Christensen 99*30588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(NULL)) != NULL) 100*30588217SMike Christensen return (dsp); 101*30588217SMike Christensen 102*30588217SMike Christensen /* double the size */ 103*30588217SMike Christensen newndslib = ndslib << 1; 104*30588217SMike Christensen if ((dslibtab = realloc(dslibtab, newndslib * sizeof (dslibentry_t))) 105*30588217SMike Christensen == NULL) 106*30588217SMike Christensen return (NULL); 107*30588217SMike Christensen dsp = &dslibtab[ndslib]; 108*30588217SMike Christensen (void) memset(dsp, 0, (newndslib - ndslib) * sizeof (dslibentry_t)); 109*30588217SMike Christensen ndslib = newndslib; 110*30588217SMike Christensen return (dsp); 111*30588217SMike Christensen } 112*30588217SMike Christensen 113*30588217SMike Christensen static dslibentry_t * 114*30588217SMike Christensen ds_lookup_dslibentry(char *service, boolean_t is_client) 115*30588217SMike Christensen { 116*30588217SMike Christensen int i; 117*30588217SMike Christensen dslibentry_t *dsp; 118*30588217SMike Christensen uint_t is_client_flag = is_client ? VLDS_REG_CLIENT : 0; 119*30588217SMike Christensen 120*30588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 121*30588217SMike Christensen if (dsp->dsl_hdl != NULL && 122*30588217SMike Christensen strcmp(dsp->dsl_service, service) == 0 && 123*30588217SMike Christensen (dsp->dsl_flags & VLDS_REG_CLIENT) == is_client_flag) { 124*30588217SMike Christensen return (dsp); 125*30588217SMike Christensen } 126*30588217SMike Christensen } 127*30588217SMike Christensen return (NULL); 128*30588217SMike Christensen } 129*30588217SMike Christensen 130*30588217SMike Christensen static dslibentry_t * 131*30588217SMike Christensen ds_register_dslibentry(ds_hdl_t hdl, char *service, boolean_t is_client) 132*30588217SMike Christensen { 133*30588217SMike Christensen dslibentry_t *dsp, *orig_dsp; 134*30588217SMike Christensen uint_t nhdls; 135*30588217SMike Christensen 136*30588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) 137*30588217SMike Christensen return (dsp); 138*30588217SMike Christensen 139*30588217SMike Christensen if ((orig_dsp = ds_lookup_dslibentry(service, is_client)) == NULL) { 140*30588217SMike Christensen return (NULL); 141*30588217SMike Christensen } 142*30588217SMike Christensen 143*30588217SMike Christensen /* 144*30588217SMike Christensen * Find out if we have 1 or 2 or more handles. Having one implies 145*30588217SMike Christensen * that we can reuse the current one handle for this service. 146*30588217SMike Christensen * Having two or more implies we need to allocate a new handle. 147*30588217SMike Christensen */ 148*30588217SMike Christensen if (ds_hdl_lookup(service, is_client, NULL, 2, &nhdls) != 0) 149*30588217SMike Christensen return (NULL); 150*30588217SMike Christensen 151*30588217SMike Christensen if (nhdls == 1) { 152*30588217SMike Christensen /* reuse the original structure entry */ 153*30588217SMike Christensen dsp = orig_dsp; 154*30588217SMike Christensen } else if (nhdls == 2) { 155*30588217SMike Christensen /* allocate a new structure entry */ 156*30588217SMike Christensen if ((dsp = ds_new_dslibentry()) == NULL) 157*30588217SMike Christensen return (NULL); 158*30588217SMike Christensen *dsp = *orig_dsp; 159*30588217SMike Christensen dsp->dsl_service = strdup(orig_dsp->dsl_service); 160*30588217SMike Christensen } else { 161*30588217SMike Christensen /* can't happen... */ 162*30588217SMike Christensen return (NULL); 163*30588217SMike Christensen } 164*30588217SMike Christensen dsp->dsl_hdl = hdl; 165*30588217SMike Christensen return (dsp); 166*30588217SMike Christensen } 167*30588217SMike Christensen 168*30588217SMike Christensen /* 169*30588217SMike Christensen * Want to leave an entry in the dslib table even though all the 170*30588217SMike Christensen * handles may have been unregistered for it. 171*30588217SMike Christensen */ 172*30588217SMike Christensen static void 173*30588217SMike Christensen ds_free_dslibentry(dslibentry_t *dsp, int force_unreg) 174*30588217SMike Christensen { 175*30588217SMike Christensen uint_t nhdls; 176*30588217SMike Christensen 177*30588217SMike Christensen /* 178*30588217SMike Christensen * Find out if we have 1 or 2 or more handles. Having one implies 179*30588217SMike Christensen * that we want to leave the entry alone unless this is a ds_unreg_hdl 180*30588217SMike Christensen * (force_unreg is true). 181*30588217SMike Christensen */ 182*30588217SMike Christensen if (ds_hdl_lookup(dsp->dsl_service, 183*30588217SMike Christensen (dsp->dsl_flags & VLDS_REG_CLIENT) != 0, NULL, 2, &nhdls) != 0) { 184*30588217SMike Christensen /* should never happen */ 185*30588217SMike Christensen return; 186*30588217SMike Christensen } 187*30588217SMike Christensen 188*30588217SMike Christensen if ((nhdls == 1 && force_unreg) || nhdls == 2) { 189*30588217SMike Christensen dsp->dsl_hdl = NULL; 190*30588217SMike Christensen if (dsp->dsl_service) { 191*30588217SMike Christensen free(dsp->dsl_service); 192*30588217SMike Christensen } 193*30588217SMike Christensen (void) memset(dsp, 0, sizeof (dslibentry_t)); 194*30588217SMike Christensen } 195*30588217SMike Christensen } 196*30588217SMike Christensen 197*30588217SMike Christensen /*ARGSUSED*/ 198*30588217SMike Christensen static int 199*30588217SMike Christensen ds_recv(sysevent_t *sep, void *arg) 200*30588217SMike Christensen { 201*30588217SMike Christensen nvlist_t *nvl; 202*30588217SMike Christensen uint64_t hdl; 203*30588217SMike Christensen ds_ver_t ver; 204*30588217SMike Christensen ds_domain_hdl_t dhdl; 205*30588217SMike Christensen uchar_t *bufp; 206*30588217SMike Christensen boolean_t is_client; 207*30588217SMike Christensen uint_t buflen; 208*30588217SMike Christensen char *subclass; 209*30588217SMike Christensen char *servicep; 210*30588217SMike Christensen dslibentry_t *dsp; 211*30588217SMike Christensen ds_cb_arg_t cb_arg; 212*30588217SMike Christensen 213*30588217SMike Christensen subclass = sysevent_get_subclass_name(sep); 214*30588217SMike Christensen if (sysevent_get_attr_list(sep, &nvl) != 0) { 215*30588217SMike Christensen return (0); 216*30588217SMike Christensen } 217*30588217SMike Christensen 218*30588217SMike Christensen if (nvlist_lookup_uint64(nvl, VLDS_HDL, &hdl) == 0) { 219*30588217SMike Christensen if (strcmp(subclass, ESC_VLDS_REGISTER) == 0) { 220*30588217SMike Christensen void (*reg_cb)(ds_hdl_t, ds_cb_arg_t, ds_ver_t *, 221*30588217SMike Christensen ds_domain_hdl_t) = NULL; 222*30588217SMike Christensen 223*30588217SMike Christensen if (nvlist_lookup_string(nvl, VLDS_SERVICE_ID, 224*30588217SMike Christensen &servicep) == 0 && 225*30588217SMike Christensen nvlist_lookup_boolean_value(nvl, VLDS_ISCLIENT, 226*30588217SMike Christensen &is_client) == 0) { 227*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 228*30588217SMike Christensen if ((dsp = ds_register_dslibentry(hdl, 229*30588217SMike Christensen servicep, is_client)) != NULL) { 230*30588217SMike Christensen reg_cb = dsp->dsl_ops.ds_reg_cb; 231*30588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 232*30588217SMike Christensen } 233*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 234*30588217SMike Christensen if (reg_cb != NULL && 235*30588217SMike Christensen nvlist_lookup_uint64(nvl, VLDS_DOMAIN_HDL, 236*30588217SMike Christensen &dhdl) == 0 && 237*30588217SMike Christensen nvlist_lookup_uint16(nvl, VLDS_VER_MAJOR, 238*30588217SMike Christensen &ver.major) == 0 && 239*30588217SMike Christensen nvlist_lookup_uint16(nvl, VLDS_VER_MINOR, 240*30588217SMike Christensen &ver.minor) == 0) { 241*30588217SMike Christensen (reg_cb)((ds_hdl_t)hdl, cb_arg, &ver, 242*30588217SMike Christensen dhdl); 243*30588217SMike Christensen } 244*30588217SMike Christensen } 245*30588217SMike Christensen } else if (strcmp(subclass, ESC_VLDS_UNREGISTER) == 0) { 246*30588217SMike Christensen void (*unreg_cb)(ds_hdl_t, ds_cb_arg_t) = NULL; 247*30588217SMike Christensen 248*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 249*30588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 250*30588217SMike Christensen unreg_cb = dsp->dsl_ops.ds_unreg_cb; 251*30588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 252*30588217SMike Christensen ds_free_dslibentry(dsp, 0); 253*30588217SMike Christensen } 254*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 255*30588217SMike Christensen if (unreg_cb != NULL) { 256*30588217SMike Christensen (unreg_cb)((ds_hdl_t)hdl, cb_arg); 257*30588217SMike Christensen } 258*30588217SMike Christensen } else if (strcmp(subclass, ESC_VLDS_DATA) == 0) { 259*30588217SMike Christensen void (*data_cb)(ds_hdl_t, ds_cb_arg_t, void *, 260*30588217SMike Christensen size_t) = NULL; 261*30588217SMike Christensen 262*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 263*30588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 264*30588217SMike Christensen data_cb = dsp->dsl_ops.ds_data_cb; 265*30588217SMike Christensen cb_arg = dsp->dsl_ops.cb_arg; 266*30588217SMike Christensen } 267*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 268*30588217SMike Christensen if (data_cb != NULL && 269*30588217SMike Christensen nvlist_lookup_byte_array(nvl, VLDS_DATA, &bufp, 270*30588217SMike Christensen &buflen) == 0) { 271*30588217SMike Christensen (data_cb)((ds_hdl_t)hdl, cb_arg, bufp, buflen); 272*30588217SMike Christensen } 273*30588217SMike Christensen } 274*30588217SMike Christensen } 275*30588217SMike Christensen nvlist_free(nvl); 276*30588217SMike Christensen return (0); 277*30588217SMike Christensen } 278*30588217SMike Christensen 279*30588217SMike Christensen static void 280*30588217SMike Christensen ds_string_arg(vlds_string_t *dsp, char *str) 281*30588217SMike Christensen { 282*30588217SMike Christensen if (str == NULL) { 283*30588217SMike Christensen dsp->vlds_strp = NULL; 284*30588217SMike Christensen dsp->vlds_strlen = 0; 285*30588217SMike Christensen } else { 286*30588217SMike Christensen dsp->vlds_strp = PTRTOUINT64(str); 287*30588217SMike Christensen dsp->vlds_strlen = strlen(str) + 1; 288*30588217SMike Christensen } 289*30588217SMike Christensen } 290*30588217SMike Christensen 291*30588217SMike Christensen static int 292*30588217SMike Christensen ds_init_sysev(void) 293*30588217SMike Christensen { 294*30588217SMike Christensen char evchan_name[MAX_CHNAME_LEN]; 295*30588217SMike Christensen 296*30588217SMike Christensen (void) sprintf(evchan_name, VLDS_SYSEV_CHAN_FMT, (int)getpid()); 297*30588217SMike Christensen if (sysevent_evc_bind(evchan_name, &ds_evchan, 0) != 0) { 298*30588217SMike Christensen return (errno); 299*30588217SMike Christensen } 300*30588217SMike Christensen if (sysevent_evc_subscribe(ds_evchan, ds_sid_name, EC_VLDS, 301*30588217SMike Christensen ds_recv, NULL, 0) != 0) { 302*30588217SMike Christensen sysevent_evc_unbind(ds_evchan); 303*30588217SMike Christensen ds_evchan = NULL; 304*30588217SMike Christensen return (errno); 305*30588217SMike Christensen } 306*30588217SMike Christensen return (0); 307*30588217SMike Christensen } 308*30588217SMike Christensen 309*30588217SMike Christensen int 310*30588217SMike Christensen ds_init(void) 311*30588217SMike Christensen { 312*30588217SMike Christensen if (ds_fd >= 0) 313*30588217SMike Christensen return (0); 314*30588217SMike Christensen 315*30588217SMike Christensen if ((ds_fd = open(vlds_device, 0)) < 0) 316*30588217SMike Christensen return (errno); 317*30588217SMike Christensen 318*30588217SMike Christensen if (dslibtab == NULL) { 319*30588217SMike Christensen if ((dslibtab = malloc(sizeof (dslibentry_t) * ndslib)) == NULL) 320*30588217SMike Christensen return (errno = ENOMEM); 321*30588217SMike Christensen ndslib = MIN_DSLIB_ENTRIES; 322*30588217SMike Christensen (void) memset(dslibtab, 0, sizeof (dslibentry_t) * ndslib); 323*30588217SMike Christensen } 324*30588217SMike Christensen 325*30588217SMike Christensen (void) mutex_init(&dslib_lock, USYNC_THREAD, NULL); 326*30588217SMike Christensen return (0); 327*30588217SMike Christensen } 328*30588217SMike Christensen 329*30588217SMike Christensen static int 330*30588217SMike Christensen ds_register(ds_capability_t *cap, ds_ops_t *ops, uint_t flags) 331*30588217SMike Christensen { 332*30588217SMike Christensen dslibentry_t *dsp; 333*30588217SMike Christensen vlds_svc_reg_arg_t vlds_arg; 334*30588217SMike Christensen vlds_cap_t vlds_cap; 335*30588217SMike Christensen vlds_ver_t vlds_vers[VLDS_MAX_VERS]; 336*30588217SMike Christensen uint64_t hdl_arg; 337*30588217SMike Christensen ds_hdl_t hdl; 338*30588217SMike Christensen uint_t nhdls; 339*30588217SMike Christensen int i; 340*30588217SMike Christensen 341*30588217SMike Christensen if (cap == NULL || ops == NULL || cap->svc_id == NULL || 342*30588217SMike Christensen cap->vers == NULL || (flags & (~VLDS_REG_CLIENT)) != 0) { 343*30588217SMike Christensen return (errno = EINVAL); 344*30588217SMike Christensen } 345*30588217SMike Christensen 346*30588217SMike Christensen if (cap->nvers > VLDS_MAX_VERS) { 347*30588217SMike Christensen return (errno = EINVAL); 348*30588217SMike Christensen } 349*30588217SMike Christensen 350*30588217SMike Christensen if (ds_fd < 0 && (errno = ds_init()) != 0) { 351*30588217SMike Christensen return (errno); 352*30588217SMike Christensen } 353*30588217SMike Christensen 354*30588217SMike Christensen if (ds_hdl_lookup(cap->svc_id, (flags & VLDS_REG_CLIENT), NULL, 1, 355*30588217SMike Christensen &nhdls) == 0 && nhdls == 1) { 356*30588217SMike Christensen return (errno = EALREADY); 357*30588217SMike Christensen } 358*30588217SMike Christensen 359*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 360*30588217SMike Christensen if ((dsp = ds_new_dslibentry()) == NULL) { 361*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 362*30588217SMike Christensen return (errno = ENOMEM); 363*30588217SMike Christensen } 364*30588217SMike Christensen 365*30588217SMike Christensen /* Setup device driver capability structure. */ 366*30588217SMike Christensen 367*30588217SMike Christensen /* service string */ 368*30588217SMike Christensen ds_string_arg(&vlds_cap.vlds_service, cap->svc_id); 369*30588217SMike Christensen 370*30588217SMike Christensen /* version array */ 371*30588217SMike Christensen for (i = 0; i < cap->nvers; i++) { 372*30588217SMike Christensen vlds_vers[i].vlds_major = cap->vers[i].major; 373*30588217SMike Christensen vlds_vers[i].vlds_minor = cap->vers[i].minor; 374*30588217SMike Christensen } 375*30588217SMike Christensen vlds_cap.vlds_versp = PTRTOUINT64(vlds_vers); 376*30588217SMike Christensen vlds_cap.vlds_nver = cap->nvers; 377*30588217SMike Christensen 378*30588217SMike Christensen /* 379*30588217SMike Christensen * Format args for VLDS_SVC_REG ioctl. 380*30588217SMike Christensen */ 381*30588217SMike Christensen 382*30588217SMike Christensen vlds_arg.vlds_capp = PTRTOUINT64(&vlds_cap); 383*30588217SMike Christensen 384*30588217SMike Christensen /* op flags */ 385*30588217SMike Christensen if (ops->ds_reg_cb != NULL) 386*30588217SMike Christensen flags |= VLDS_REGCB_VALID; 387*30588217SMike Christensen if (ops->ds_unreg_cb != NULL) 388*30588217SMike Christensen flags |= VLDS_UNREGCB_VALID; 389*30588217SMike Christensen if (ops->ds_data_cb != NULL) 390*30588217SMike Christensen flags |= VLDS_DATACB_VALID; 391*30588217SMike Christensen vlds_arg.vlds_reg_flags = flags; 392*30588217SMike Christensen 393*30588217SMike Christensen /* returned handle */ 394*30588217SMike Christensen vlds_arg.vlds_hdlp = PTRTOUINT64(&hdl_arg); 395*30588217SMike Christensen 396*30588217SMike Christensen if (ioctl(ds_fd, VLDS_SVC_REG, &vlds_arg) < 0) { 397*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 398*30588217SMike Christensen return (errno); 399*30588217SMike Christensen } 400*30588217SMike Christensen 401*30588217SMike Christensen /* 402*30588217SMike Christensen * Setup user callback sysevent channel. 403*30588217SMike Christensen */ 404*30588217SMike Christensen if ((flags & VLDS_ANYCB_VALID) != 0 && ds_evchan == NULL && 405*30588217SMike Christensen ds_init_sysev() != 0) { 406*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 407*30588217SMike Christensen (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg); 408*30588217SMike Christensen return (errno); 409*30588217SMike Christensen } 410*30588217SMike Christensen 411*30588217SMike Christensen hdl = hdl_arg; 412*30588217SMike Christensen 413*30588217SMike Christensen /* 414*30588217SMike Christensen * Set entry values in dslibtab. 415*30588217SMike Christensen */ 416*30588217SMike Christensen dsp->dsl_hdl = hdl; 417*30588217SMike Christensen dsp->dsl_flags = flags; 418*30588217SMike Christensen dsp->dsl_service = strdup(cap->svc_id); 419*30588217SMike Christensen dsp->dsl_ops = *ops; 420*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 421*30588217SMike Christensen return (0); 422*30588217SMike Christensen } 423*30588217SMike Christensen 424*30588217SMike Christensen /* 425*30588217SMike Christensen * Registers a service provider. Kicks off the handshake with other 426*30588217SMike Christensen * domain(s) to announce servce. Callback events are as described above. 427*30588217SMike Christensen */ 428*30588217SMike Christensen int 429*30588217SMike Christensen ds_svc_reg(ds_capability_t *cap, ds_ops_t *ops) 430*30588217SMike Christensen { 431*30588217SMike Christensen return (ds_register(cap, ops, 0)); 432*30588217SMike Christensen } 433*30588217SMike Christensen 434*30588217SMike Christensen /* 435*30588217SMike Christensen * Registers interest in a service from a specific domain. When that 436*30588217SMike Christensen * service is registered, the register callback is invoked. When that 437*30588217SMike Christensen * service is unregistered, the unregister callback is invoked. When 438*30588217SMike Christensen * data is received, the receive data callback is invoked. 439*30588217SMike Christensen */ 440*30588217SMike Christensen int 441*30588217SMike Christensen ds_clnt_reg(ds_capability_t *cap, ds_ops_t *ops) 442*30588217SMike Christensen { 443*30588217SMike Christensen return (ds_register(cap, ops, VLDS_REG_CLIENT)); 444*30588217SMike Christensen } 445*30588217SMike Christensen 446*30588217SMike Christensen /* 447*30588217SMike Christensen * Given a service name and type, returns the existing handle(s), if 448*30588217SMike Christensen * one or more exist. This could be used to poll for the connection being 449*30588217SMike Christensen * registered or unregistered, rather than using the register/unregister 450*30588217SMike Christensen * callbacks. 451*30588217SMike Christensen */ 452*30588217SMike Christensen int 453*30588217SMike Christensen ds_hdl_lookup(char *service, boolean_t is_client, ds_hdl_t *hdlsp, 454*30588217SMike Christensen uint_t maxhdls, uint_t *nhdlsp) 455*30588217SMike Christensen { 456*30588217SMike Christensen vlds_hdl_lookup_arg_t vlds_arg; 457*30588217SMike Christensen uint64_t nhdls_arg; 458*30588217SMike Christensen 459*30588217SMike Christensen errno = 0; 460*30588217SMike Christensen if (ds_fd < 0) { 461*30588217SMike Christensen return (errno = EBADF); 462*30588217SMike Christensen } 463*30588217SMike Christensen 464*30588217SMike Christensen if (service == NULL) { 465*30588217SMike Christensen return (errno = EINVAL); 466*30588217SMike Christensen } 467*30588217SMike Christensen 468*30588217SMike Christensen ds_string_arg(&vlds_arg.vlds_service, service); 469*30588217SMike Christensen vlds_arg.vlds_isclient = is_client ? VLDS_REG_CLIENT : 0; 470*30588217SMike Christensen vlds_arg.vlds_hdlsp = PTRTOUINT64(hdlsp); 471*30588217SMike Christensen vlds_arg.vlds_maxhdls = maxhdls; 472*30588217SMike Christensen vlds_arg.vlds_nhdlsp = PTRTOUINT64(&nhdls_arg); 473*30588217SMike Christensen 474*30588217SMike Christensen if (ioctl(ds_fd, VLDS_HDL_LOOKUP, &vlds_arg) < 0) { 475*30588217SMike Christensen return (errno); 476*30588217SMike Christensen } 477*30588217SMike Christensen 478*30588217SMike Christensen *nhdlsp = nhdls_arg; 479*30588217SMike Christensen return (0); 480*30588217SMike Christensen } 481*30588217SMike Christensen 482*30588217SMike Christensen /* 483*30588217SMike Christensen * Given a handle, return its associated domain. 484*30588217SMike Christensen */ 485*30588217SMike Christensen int 486*30588217SMike Christensen ds_domain_lookup(ds_hdl_t hdl, ds_domain_hdl_t *dhdlp) 487*30588217SMike Christensen { 488*30588217SMike Christensen vlds_dmn_lookup_arg_t vlds_arg; 489*30588217SMike Christensen uint64_t dhdl_arg; 490*30588217SMike Christensen 491*30588217SMike Christensen if (ds_fd < 0) { 492*30588217SMike Christensen return (errno = EBADF); 493*30588217SMike Christensen } 494*30588217SMike Christensen 495*30588217SMike Christensen vlds_arg.vlds_hdl = hdl; 496*30588217SMike Christensen vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg); 497*30588217SMike Christensen 498*30588217SMike Christensen if (ioctl(ds_fd, VLDS_DMN_LOOKUP, &vlds_arg) < 0) { 499*30588217SMike Christensen return (errno); 500*30588217SMike Christensen } 501*30588217SMike Christensen 502*30588217SMike Christensen if (dhdlp) { 503*30588217SMike Christensen *dhdlp = dhdl_arg; 504*30588217SMike Christensen } 505*30588217SMike Christensen 506*30588217SMike Christensen return (0); 507*30588217SMike Christensen } 508*30588217SMike Christensen 509*30588217SMike Christensen /* 510*30588217SMike Christensen * Unregisters either a service or an interest in that service 511*30588217SMike Christensen * indicated by the supplied handle. 512*30588217SMike Christensen */ 513*30588217SMike Christensen int 514*30588217SMike Christensen ds_unreg_hdl(ds_hdl_t hdl) 515*30588217SMike Christensen { 516*30588217SMike Christensen dslibentry_t *dsp; 517*30588217SMike Christensen vlds_unreg_hdl_arg_t vlds_arg; 518*30588217SMike Christensen 519*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 520*30588217SMike Christensen if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) { 521*30588217SMike Christensen ds_free_dslibentry(dsp, 1); 522*30588217SMike Christensen } 523*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 524*30588217SMike Christensen 525*30588217SMike Christensen if (ds_fd >= 0) { 526*30588217SMike Christensen vlds_arg.vlds_hdl = hdl; 527*30588217SMike Christensen (void) ioctl(ds_fd, VLDS_UNREG_HDL, &vlds_arg); 528*30588217SMike Christensen } 529*30588217SMike Christensen 530*30588217SMike Christensen return (0); 531*30588217SMike Christensen } 532*30588217SMike Christensen 533*30588217SMike Christensen /* 534*30588217SMike Christensen * Send data to the appropriate service provider or client 535*30588217SMike Christensen * indicated by the provided handle. The sender will block 536*30588217SMike Christensen * until the message has been sent. There is no guarantee 537*30588217SMike Christensen * that multiple calls to ds_send_msg by the same thread 538*30588217SMike Christensen * will result in the data showing up at the receiver in 539*30588217SMike Christensen * the same order as sent. If multiple messages are required, 540*30588217SMike Christensen * it will be up to the sender and receiver to implement a 541*30588217SMike Christensen * protocol. 542*30588217SMike Christensen */ 543*30588217SMike Christensen int 544*30588217SMike Christensen ds_send_msg(ds_hdl_t hdl, void *buf, size_t buflen) 545*30588217SMike Christensen { 546*30588217SMike Christensen vlds_send_msg_arg_t vlds_arg; 547*30588217SMike Christensen 548*30588217SMike Christensen if (ds_fd < 0) { 549*30588217SMike Christensen return (errno = EBADF); 550*30588217SMike Christensen } 551*30588217SMike Christensen 552*30588217SMike Christensen vlds_arg.vlds_hdl = hdl; 553*30588217SMike Christensen vlds_arg.vlds_bufp = PTRTOUINT64(buf); 554*30588217SMike Christensen vlds_arg.vlds_buflen = buflen; 555*30588217SMike Christensen 556*30588217SMike Christensen if (ioctl(ds_fd, VLDS_SEND_MSG, &vlds_arg) < 0) { 557*30588217SMike Christensen return (errno); 558*30588217SMike Christensen } 559*30588217SMike Christensen 560*30588217SMike Christensen return (0); 561*30588217SMike Christensen } 562*30588217SMike Christensen 563*30588217SMike Christensen /* 564*30588217SMike Christensen * Receive data from the appropriate service provider or client 565*30588217SMike Christensen * indicated by the provided handle. The sender will block 566*30588217SMike Christensen * until a message has been received. 567*30588217SMike Christensen */ 568*30588217SMike Christensen int 569*30588217SMike Christensen ds_recv_msg(ds_hdl_t hdl, void *buf, size_t buflen, size_t *msglen) 570*30588217SMike Christensen { 571*30588217SMike Christensen vlds_recv_msg_arg_t vlds_arg; 572*30588217SMike Christensen uint64_t msglen_arg; 573*30588217SMike Christensen 574*30588217SMike Christensen if (ds_fd < 0) { 575*30588217SMike Christensen return (errno = EBADF); 576*30588217SMike Christensen } 577*30588217SMike Christensen 578*30588217SMike Christensen vlds_arg.vlds_hdl = hdl; 579*30588217SMike Christensen vlds_arg.vlds_bufp = PTRTOUINT64(buf); 580*30588217SMike Christensen vlds_arg.vlds_buflen = buflen; 581*30588217SMike Christensen vlds_arg.vlds_msglenp = PTRTOUINT64(&msglen_arg); 582*30588217SMike Christensen 583*30588217SMike Christensen if (ioctl(ds_fd, VLDS_RECV_MSG, &vlds_arg) < 0) { 584*30588217SMike Christensen if (errno == EFBIG && msglen) { 585*30588217SMike Christensen *msglen = msglen_arg; 586*30588217SMike Christensen } 587*30588217SMike Christensen return (errno); 588*30588217SMike Christensen } 589*30588217SMike Christensen 590*30588217SMike Christensen if (msglen) { 591*30588217SMike Christensen *msglen = msglen_arg; 592*30588217SMike Christensen } 593*30588217SMike Christensen 594*30588217SMike Christensen return (0); 595*30588217SMike Christensen } 596*30588217SMike Christensen 597*30588217SMike Christensen int 598*30588217SMike Christensen ds_isready(ds_hdl_t hdl, boolean_t *is_ready) 599*30588217SMike Christensen { 600*30588217SMike Christensen vlds_hdl_isready_arg_t vlds_arg; 601*30588217SMike Christensen uint64_t is_ready_arg; 602*30588217SMike Christensen 603*30588217SMike Christensen if (ds_fd < 0) { 604*30588217SMike Christensen return (errno = EBADF); 605*30588217SMike Christensen } 606*30588217SMike Christensen 607*30588217SMike Christensen vlds_arg.vlds_hdl = hdl; 608*30588217SMike Christensen vlds_arg.vlds_isreadyp = PTRTOUINT64(&is_ready_arg); 609*30588217SMike Christensen 610*30588217SMike Christensen if (ioctl(ds_fd, VLDS_HDL_ISREADY, &vlds_arg) < 0) { 611*30588217SMike Christensen return (errno); 612*30588217SMike Christensen } 613*30588217SMike Christensen 614*30588217SMike Christensen *is_ready = (is_ready_arg != 0); 615*30588217SMike Christensen return (0); 616*30588217SMike Christensen } 617*30588217SMike Christensen 618*30588217SMike Christensen /* 619*30588217SMike Christensen * Given a domain name, return its associated domain handle. 620*30588217SMike Christensen */ 621*30588217SMike Christensen int 622*30588217SMike Christensen ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp) 623*30588217SMike Christensen { 624*30588217SMike Christensen vlds_dom_nam2hdl_arg_t vlds_arg; 625*30588217SMike Christensen uint64_t dhdl_arg; 626*30588217SMike Christensen 627*30588217SMike Christensen if (ds_fd < 0) { 628*30588217SMike Christensen return (errno = EBADF); 629*30588217SMike Christensen } 630*30588217SMike Christensen 631*30588217SMike Christensen ds_string_arg(&vlds_arg.vlds_domain_name, domain_name); 632*30588217SMike Christensen vlds_arg.vlds_dhdlp = PTRTOUINT64(&dhdl_arg); 633*30588217SMike Christensen 634*30588217SMike Christensen if (ioctl(ds_fd, VLDS_DOM_NAM2HDL, &vlds_arg) < 0) { 635*30588217SMike Christensen return (errno); 636*30588217SMike Christensen } 637*30588217SMike Christensen 638*30588217SMike Christensen if (dhdlp) { 639*30588217SMike Christensen *dhdlp = dhdl_arg; 640*30588217SMike Christensen } 641*30588217SMike Christensen 642*30588217SMike Christensen return (0); 643*30588217SMike Christensen } 644*30588217SMike Christensen 645*30588217SMike Christensen /* 646*30588217SMike Christensen * Given a domain handle, return its associated domain name. 647*30588217SMike Christensen */ 648*30588217SMike Christensen int 649*30588217SMike Christensen ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char *domain_name, uint_t maxnamlen) 650*30588217SMike Christensen { 651*30588217SMike Christensen vlds_dom_hdl2nam_arg_t vlds_arg; 652*30588217SMike Christensen 653*30588217SMike Christensen if (ds_fd < 0) { 654*30588217SMike Christensen return (errno = EBADF); 655*30588217SMike Christensen } 656*30588217SMike Christensen 657*30588217SMike Christensen vlds_arg.vlds_dhdl = dhdl; 658*30588217SMike Christensen vlds_arg.vlds_domain_name.vlds_strp = PTRTOUINT64(domain_name); 659*30588217SMike Christensen vlds_arg.vlds_domain_name.vlds_strlen = maxnamlen; 660*30588217SMike Christensen 661*30588217SMike Christensen if (ioctl(ds_fd, VLDS_DOM_HDL2NAM, &vlds_arg) < 0) { 662*30588217SMike Christensen return (errno); 663*30588217SMike Christensen } 664*30588217SMike Christensen 665*30588217SMike Christensen return (0); 666*30588217SMike Christensen } 667*30588217SMike Christensen 668*30588217SMike Christensen void 669*30588217SMike Christensen ds_unreg_svc(char *service, boolean_t is_client) 670*30588217SMike Christensen { 671*30588217SMike Christensen ds_hdl_t hdl; 672*30588217SMike Christensen uint_t nhdls; 673*30588217SMike Christensen 674*30588217SMike Christensen while (ds_hdl_lookup(service, is_client, &hdl, 1, &nhdls) == 0 && 675*30588217SMike Christensen nhdls == 1) { 676*30588217SMike Christensen (void) ds_unreg_hdl(hdl); 677*30588217SMike Christensen } 678*30588217SMike Christensen } 679*30588217SMike Christensen 680*30588217SMike Christensen void 681*30588217SMike Christensen ds_fini(void) 682*30588217SMike Christensen { 683*30588217SMike Christensen int i; 684*30588217SMike Christensen dslibentry_t *dsp; 685*30588217SMike Christensen 686*30588217SMike Christensen if (ds_fd >= 0) { 687*30588217SMike Christensen (void) close(ds_fd); 688*30588217SMike Christensen ds_fd = -1; 689*30588217SMike Christensen } 690*30588217SMike Christensen if (ds_evchan) { 691*30588217SMike Christensen (void) sysevent_evc_unsubscribe(ds_evchan, ds_sid_name); 692*30588217SMike Christensen (void) sysevent_evc_unbind(ds_evchan); 693*30588217SMike Christensen ds_evchan = NULL; 694*30588217SMike Christensen } 695*30588217SMike Christensen if (ndslib > 0) { 696*30588217SMike Christensen (void) mutex_lock(&dslib_lock); 697*30588217SMike Christensen for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) { 698*30588217SMike Christensen if (dsp->dsl_hdl == NULL) 699*30588217SMike Christensen continue; 700*30588217SMike Christensen if (dsp->dsl_service) { 701*30588217SMike Christensen free(dsp->dsl_service); 702*30588217SMike Christensen } 703*30588217SMike Christensen } 704*30588217SMike Christensen free(dslibtab); 705*30588217SMike Christensen ndslib = 0; 706*30588217SMike Christensen dslibtab = NULL; 707*30588217SMike Christensen (void) mutex_unlock(&dslib_lock); 708*30588217SMike Christensen (void) mutex_destroy(&dslib_lock); 709*30588217SMike Christensen } 710*30588217SMike Christensen } 711