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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 #include <uuid/uuid.h>
41 * Global list of allocated handles. Handles are used in various
42 * server-side RPC functions: typically, issued when a service is
43 * opened and obsoleted when it is closed. Clients should treat
44 * handles as opaque data.
46 static ndr_handle_t
*ndr_handle_list
;
47 static mutex_t ndr_handle_lock
;
50 * Table of registered services.
52 #define NDR_MAX_SERVICES 32
53 static ndr_service_t
*ndr_services
[NDR_MAX_SERVICES
];
60 * -1 Duplicate service
65 ndr_svc_register(ndr_service_t
*svc
)
71 for (i
= 0; i
< NDR_MAX_SERVICES
; i
++) {
72 if ((p
= ndr_services
[i
]) == NULL
) {
81 if (strcasecmp(p
->name
, svc
->name
) == 0)
88 ndr_services
[free_slot
] = svc
;
93 ndr_svc_unregister(ndr_service_t
*svc
)
97 for (i
= 0; i
< NDR_MAX_SERVICES
; i
++) {
98 if (ndr_services
[i
] == svc
)
99 ndr_services
[i
] = NULL
;
104 ndr_svc_find_stub(ndr_service_t
*svc
, int opnum
)
106 ndr_stub_table_t
*ste
;
108 for (ste
= svc
->stub_table
; ste
->func
; ste
++) {
109 if (ste
->opnum
== opnum
)
117 ndr_svc_lookup_name(const char *name
)
122 for (i
= 0; i
< NDR_MAX_SERVICES
; i
++) {
123 if ((svc
= ndr_services
[i
]) == NULL
)
126 if (strcasecmp(name
, svc
->name
) != 0)
129 ndo_printf(0, 0, "%s %s", svc
->name
, svc
->desc
);
137 ndr_svc_lookup_uuid(ndr_uuid_t
*as_uuid
, int as_vers
,
138 ndr_uuid_t
*ts_uuid
, int ts_vers
)
141 char abstract_syntax
[UUID_PRINTABLE_STRING_LENGTH
];
142 char transfer_syntax
[UUID_PRINTABLE_STRING_LENGTH
];
146 ndr_uuid_unparse(as_uuid
, abstract_syntax
);
149 ndr_uuid_unparse(ts_uuid
, transfer_syntax
);
151 for (i
= 0; i
< NDR_MAX_SERVICES
; i
++) {
152 if ((svc
= ndr_services
[i
]) == NULL
)
156 if (svc
->abstract_syntax_uuid
== 0)
159 if (svc
->abstract_syntax_version
!= as_vers
)
162 if (strcasecmp(abstract_syntax
,
163 svc
->abstract_syntax_uuid
))
168 if (svc
->transfer_syntax_uuid
== 0)
171 if (svc
->transfer_syntax_version
!= ts_vers
)
174 if (strcasecmp(transfer_syntax
,
175 svc
->transfer_syntax_uuid
))
179 ndo_printf(0, 0, "%s %s", svc
->name
, svc
->desc
);
183 ndo_printf(0, 0, "ndr_svc_lookup_uuid: unknown service");
184 ndo_printf(0, 0, "abstract=%s v%d, transfer=%s v%d",
185 abstract_syntax
, as_vers
, transfer_syntax
, ts_vers
);
190 * Allocate a handle for use with the server-side RPC functions.
192 * An arbitrary caller context can be associated with the handle
193 * via data; it will not be dereferenced by the handle API.
196 ndr_hdalloc(const ndr_xa_t
*xa
, const void *data
)
198 static ndr_hdid_t id
;
202 if ((hd
= malloc(sizeof (ndr_handle_t
))) == NULL
)
206 uuid_generate_random(uu
);
207 bcopy(uu
, &id
.data2
, sizeof (uuid_t
));
214 bcopy(&id
, &hd
->nh_id
, sizeof (ndr_hdid_t
));
215 hd
->nh_pipe
= xa
->pipe
;
216 hd
->nh_svc
= xa
->binding
->service
;
217 hd
->nh_data
= (void *)data
;
218 hd
->nh_data_free
= NULL
;
220 (void) mutex_lock(&ndr_handle_lock
);
221 hd
->nh_next
= ndr_handle_list
;
222 ndr_handle_list
= hd
;
223 (void) mutex_unlock(&ndr_handle_lock
);
229 * Remove a handle from the global list and free it.
232 ndr_hdfree(const ndr_xa_t
*xa
, const ndr_hdid_t
*id
)
234 ndr_service_t
*svc
= xa
->binding
->service
;
240 (void) mutex_lock(&ndr_handle_lock
);
241 pphd
= &ndr_handle_list
;
246 if (bcmp(&hd
->nh_id
, id
, sizeof (ndr_hdid_t
)) == 0) {
247 if (hd
->nh_svc
== svc
) {
254 pphd
= &(*pphd
)->nh_next
;
257 (void) mutex_unlock(&ndr_handle_lock
);
261 * Lookup a handle by id. If the handle is in the list and it matches
262 * the specified service, a pointer to it is returned. Otherwise a null
263 * pointer is returned.
266 ndr_hdlookup(const ndr_xa_t
*xa
, const ndr_hdid_t
*id
)
268 ndr_service_t
*svc
= xa
->binding
->service
;
272 (void) mutex_lock(&ndr_handle_lock
);
273 hd
= ndr_handle_list
;
276 if (bcmp(&hd
->nh_id
, id
, sizeof (ndr_hdid_t
)) == 0) {
277 if (hd
->nh_svc
!= svc
)
279 (void) mutex_unlock(&ndr_handle_lock
);
286 (void) mutex_unlock(&ndr_handle_lock
);
291 * Called when a pipe is closed to release any associated handles.
294 ndr_hdclose(ndr_pipe_t
*pipe
)
299 (void) mutex_lock(&ndr_handle_lock
);
300 pphd
= &ndr_handle_list
;
305 if (hd
->nh_pipe
== pipe
) {
308 if (hd
->nh_data_free
)
309 (*hd
->nh_data_free
)(hd
->nh_data
);
315 pphd
= &(*pphd
)->nh_next
;
318 (void) mutex_unlock(&ndr_handle_lock
);
322 * Convert a UUID to a string.
325 ndr_uuid_unparse(ndr_uuid_t
*uuid
, char *out
)
327 (void) sprintf(out
, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
328 uuid
->data1
, uuid
->data2
, uuid
->data3
,
329 uuid
->data4
[0], uuid
->data4
[1],
330 uuid
->data4
[2], uuid
->data4
[3],
331 uuid
->data4
[4], uuid
->data4
[5],
332 uuid
->data4
[6], uuid
->data4
[7]);
336 * Convert a string to a UUID.
339 ndr_uuid_parse(char *in
, ndr_uuid_t
*uuid
)
346 if (strlen(in
) != UUID_PRINTABLE_STRING_LENGTH
- 1)
349 uuid
->data1
= strtoul(p
, &p
, 16);
354 uuid
->data2
= strtol(p
, &p
, 16);
359 uuid
->data3
= strtol(p
, &p
, 16);
364 for (i
= 0; i
< 8; i
++) {
368 if (p
[0] == 0 || p
[1] == 0)
374 uuid
->data4
[i
] = strtol(buf
, &q
, 16);
386 ndr_svc_binding_pool_init(ndr_binding_t
**headpp
, ndr_binding_t pool
[],
389 ndr_binding_t
*head
= NULL
;
392 for (ix
= n_pool
- 1; ix
>= 0; ix
--) {
393 pool
[ix
].next
= head
;
394 pool
[ix
].service
= NULL
;
395 pool
[ix
].p_cont_id
= 0xffff;
396 pool
[ix
].instance_specific
= 0;
404 ndr_svc_find_binding(ndr_xa_t
*mxa
, ndr_p_context_id_t p_cont_id
)
406 ndr_binding_t
*mbind
;
408 for (mbind
= mxa
->binding_list
; mbind
; mbind
= mbind
->next
) {
409 if (mbind
->service
!= NULL
&&
410 mbind
->which_side
== NDR_BIND_SIDE_SERVER
&&
411 mbind
->p_cont_id
== p_cont_id
)
419 ndr_svc_new_binding(ndr_xa_t
*mxa
)
421 ndr_binding_t
*mbind
;
423 for (mbind
= mxa
->binding_list
; mbind
; mbind
= mbind
->next
) {
424 if (mbind
->service
== NULL
)
432 * Move bytes between a buffer and a uio structure.
433 * The transfer direction is controlled by rw:
434 * UIO_READ: transfer from buf to uio
435 * UIO_WRITE: transfer from uio to buf
437 * Returns the number of bytes moved.
440 ndr_uiomove(caddr_t buf
, size_t buflen
, enum uio_rw rw
, struct uio
*uio
)
443 int reading
= (rw
== UIO_READ
);
447 assert(rw
== UIO_READ
|| rw
== UIO_WRITE
);
449 while (buflen
&& uio
->uio_resid
&& uio
->uio_iovcnt
) {
451 if ((nbytes
= iov
->iov_len
) == 0) {
461 bcopy(buf
, iov
->iov_base
, nbytes
);
463 bcopy(iov
->iov_base
, buf
, nbytes
);
465 iov
->iov_base
+= nbytes
;
466 iov
->iov_len
-= nbytes
;
467 uio
->uio_resid
-= nbytes
;
468 uio
->uio_offset
+= nbytes
;