xref: /titanic_53/usr/src/lib/libds/common/libds.c (revision 30588217a56ff2c9137248fb2e5065c4f0101459)
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