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