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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * This file contains the miscelleneous routines for libsm.so
31 #include <sys/types.h>
33 #include <sys/utsname.h>
37 #include <sys/dktp/fdisk.h>
43 #include "l_defines.h"
46 #include <sys/smedia.h>
47 #include "../inc/rmedia.h"
55 #define PATHNAME "/usr/lib/smedia/sparcv9"
57 #define PATHNAME "/usr/lib/smedia/amd64"
60 #define PATHNAME "/usr/lib/smedia"
63 #define PERROR(string) my_perror(gettext(string))
64 #define RUN_LIBSMEDIA_SERVER " /usr/lib/smedia/rpc.smserverd &\n"
67 my_perror(char *err_string
)
75 (void) fprintf(stderr
, gettext(err_string
));
76 (void) fprintf(stderr
, gettext(" : "));
82 is_server_running(rmedia_handle_t
*handle
)
85 smedia_reqping_t reqping
;
86 smedia_retping_t
*retping
;
90 char rbuf
[sizeof (smedia_services_t
) + sizeof (door_desc_t
)];
91 smserver_info
*server_info
;
94 * We will assume that we are running at level 2 or greater
95 * and attempt to contact the server using RPC mecahnisms.
96 * If that fails then we will attempt to contact the server
97 * using non-rpc mechanism. This will enable the libsmedia
98 * to be used in SINGLE user mode when inetd is not running.
99 * We expect the server to have been started manually by user.
101 * Note that "localhost" is used (vs hostname (eg, "uname -n")),
102 * as this minimizes interference with common IPSec rules.
105 clnt
= clnt_create("localhost", SMSERVERPROG
, SMSERVERVERS
,
107 if (clnt
== (CLIENT
*)NULL
) {
109 * The failure could be that we are running at level 1
111 door_fd
= open(smedia_service
, O_RDONLY
, 0644);
113 DPRINTF1("Error in opening %s\n",
118 DPRINTF1("rbuf address=%p\n", rbuf
);
119 reqping
.cnum
= SMEDIA_CNUM_PING
;
120 door_args
.data_ptr
= (char *)&reqping
;
121 door_args
.data_size
= sizeof (smedia_services_t
);
122 door_args
.desc_ptr
= NULL
;
123 door_args
.desc_num
= 0;
124 door_args
.rbuf
= rbuf
;
125 door_args
.rsize
= sizeof (rbuf
);
127 ret_val
= door_call(door_fd
, &door_args
);
128 (void) close(door_fd
);
132 DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
133 door_args
.rsize
, door_args
.data_size
,
135 retping
= (smedia_retping_t
*)(
136 (void *)door_args
.data_ptr
);
137 if (retping
->cnum
!= SMEDIA_CNUM_PING
) {
138 DPRINTF1("*** door call failed *** cnum "
139 "returned = 0x%x\n", retping
->cnum
);
144 server_info
= smserverproc_get_serverinfo_1(NULL
, clnt
);
145 if (server_info
== NULL
) {
150 if (server_info
->status
!= 0) {
153 DPRINTF1("get server_info call failed. "
154 "status = %d\n", server_info
->status
);
157 if (server_info
->vernum
!= SMSERVERVERS
) {
160 DPRINTF2("version expected = %d version "
161 "returned = %d\n", SMSERVERVERS
,
162 server_info
->vernum
);
166 door_fd
= open(smedia_service
, O_RDONLY
, 0644);
168 DPRINTF1("Error in opening %s\n", smedia_service
);
172 DPRINTF1("rbuf address=%p\n", rbuf
);
173 reqping
.cnum
= SMEDIA_CNUM_PING
;
174 door_args
.data_ptr
= (char *)&reqping
;
175 door_args
.data_size
= sizeof (smedia_services_t
);
176 door_args
.desc_ptr
= NULL
;
177 door_args
.desc_num
= 0;
178 door_args
.rbuf
= rbuf
;
179 door_args
.rsize
= sizeof (rbuf
);
181 ret_val
= door_call(door_fd
, &door_args
);
182 (void) close(door_fd
);
186 DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
187 door_args
.rsize
, door_args
.data_size
,
189 retping
= (smedia_retping_t
*)((void *)door_args
.data_ptr
);
190 if (retping
->cnum
!= SMEDIA_CNUM_PING
) {
191 DPRINTF1("*** door call failed *** cnum returned "
192 "= 0x%x\n", retping
->cnum
);
195 handle
->sm_clnt
= clnt
;
200 get_dev_library_handle(int32_t fd
)
203 void *old_handle
= NULL
;
204 struct dk_cinfo dkinfo
;
208 int32_t (*d_fcn_ptr
)(ushort_t
, ushort_t
);
209 int32_t (*v_fcn_ptr
)(void);
212 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
213 PERROR("DKIOCINFO failed");
216 DPRINTF1("dki_ctype = 0x%x\n", dkinfo
.dki_ctype
);
218 if ((pathname
= malloc(PATH_MAX
)) == NULL
) {
219 PERROR("malloc failed");
223 dirp
= opendir(PATHNAME
);
225 (void) fprintf(stderr
, gettext("Couldnot open %s\n"), PATHNAME
);
230 while ((dp
= readdir(dirp
)) != NULL
) {
231 if (strncmp("sm_", dp
->d_name
, 3) != 0) {
232 DPRINTF1("not a library %s\n", dp
->d_name
);
235 if (snprintf(pathname
, PATH_MAX
, "%s/%s",
236 PATHNAME
, dp
->d_name
) >= PATH_MAX
) {
240 handle
= dlopen(pathname
, RTLD_LAZY
);
241 if (handle
== NULL
) {
242 PERROR("Error opening library file");
245 d_fcn_ptr
= (int32_t (*)(ushort_t
, ushort_t
))dlsym(handle
,
247 if (d_fcn_ptr
== NULL
) {
248 DPRINTF("Could not find _m_device_type\n");
249 (void) dlclose(handle
);
252 ret_val
= (*d_fcn_ptr
)(dkinfo
.dki_ctype
, 0);
254 DPRINTF1("NAME %s\n", dp
->d_name
);
255 v_fcn_ptr
= (int32_t (*)(void))dlsym(handle
,
257 if (v_fcn_ptr
== NULL
) {
258 DPRINTF("Could not find _m_version_no\n");
259 (void) dlclose(handle
);
262 ret_val
= (*v_fcn_ptr
)();
263 if ((ret_val
>= 0) &&
264 (ret_val
>= SM_PLUGIN_VERSION
)) {
265 if (old_handle
!= NULL
)
266 (void) dlclose(old_handle
);
270 (void) dlclose(handle
);
273 (void) dlclose(handle
);
277 (void) closedir(dirp
);
282 call_function(rmedia_handle_t
*handle
, void *ip
, char *func_name
)
286 int32_t (*fcn_ptr
)(rmedia_handle_t
*handle
, void *ip
);
289 if (handle
== NULL
) {
290 DPRINTF("Handle is NULL\n");
294 lib_handle
= handle
->sm_lib_handle
;
295 if (handle
->sm_signature
!= LIBSMEDIA_SIGNATURE
) {
296 DPRINTF2("call_function:signature expected=0x%x, found=0x%x\n",
297 LIBSMEDIA_SIGNATURE
, handle
->sm_signature
);
302 fcn_ptr
= (int32_t (*)(rmedia_handle_t
*, void*))
303 dlsym(lib_handle
, func_name
);
304 if (fcn_ptr
== NULL
) {
305 DPRINTF1("Could not find %s\n", func_name
);
309 ret_val
= (*fcn_ptr
)(handle
, ip
);
314 release_handle(rmedia_handle_t
*handle
)
316 if (handle
== NULL
) {
317 DPRINTF("Handle is NULL\n");
321 if ((handle
->sm_dkinfo
.dki_ctype
== DKC_SCSI_CCS
) ||
322 (handle
->sm_dkinfo
.dki_ctype
== DKC_MD21
) ||
323 (handle
->sm_dkinfo
.dki_ctype
== DKC_CDROM
)) {
324 (void) close(handle
->sm_door
);
325 (void) close(handle
->sm_death_door
);
326 if (handle
->sm_buf
!= NULL
)
327 (void) munmap(handle
->sm_buf
, handle
->sm_bufsize
);
328 if (handle
->sm_clnt
!= NULL
)
329 clnt_destroy(handle
->sm_clnt
);
331 (void) close(handle
->sm_buffd
);
332 handle
->sm_signature
= 0;
333 (void) dlclose(handle
->sm_lib_handle
);
339 get_handle_from_fd(int32_t fd
)
341 rmedia_handle_t
*handle
;
343 int door_fd
, door_server
;
345 door_arg_t door_args
;
346 smedia_reqopen_t reqopen
;
347 smedia_reterror_t
*reterror
;
348 door_desc_t ddesc
[2];
349 char rbuf
[sizeof (smedia_services_t
) + sizeof (door_desc_t
)];
352 DPRINTF("smedia_get_handle called\n");
353 handle
= (rmedia_handle_t
*)malloc(sizeof (rmedia_handle_t
));
354 if (handle
== NULL
) {
355 DPRINTF("Could not allocate memory for handle\n");
358 (void) memset(handle
, 0, sizeof (rmedia_handle_t
));
360 handle
->sm_door
= -1;
361 handle
->sm_death_door
= -1;
362 handle
->sm_buffd
= -1;
363 handle
->sm_buf
= NULL
;
364 handle
->sm_bufsize
= 0;
366 if (ioctl(fd
, DKIOCINFO
, &handle
->sm_dkinfo
) == -1) {
368 PERROR("DKIOCINFO failed");
371 lib_handle
= get_dev_library_handle(fd
);
372 if (lib_handle
== NULL
) {
374 DPRINTF("lib_Handle is NULL\n");
378 DPRINTF("Handle initialised successfully.\n");
379 /* Initialise the handle elements */
380 handle
->sm_lib_handle
= lib_handle
;
381 handle
->sm_signature
= LIBSMEDIA_SIGNATURE
;
382 DPRINTF2("fd=%d signature=0x%x\n", handle
->sm_fd
, handle
->sm_signature
);
384 if ((handle
->sm_dkinfo
.dki_ctype
== DKC_SCSI_CCS
) ||
385 (handle
->sm_dkinfo
.dki_ctype
== DKC_MD21
) ||
386 (handle
->sm_dkinfo
.dki_ctype
== DKC_CDROM
)) {
388 ret_val
= is_server_running(handle
);
390 (void) dlclose(handle
->sm_lib_handle
);
394 door_fd
= open(smedia_service
, O_RDONLY
, 0644);
396 (void) dlclose(handle
->sm_lib_handle
);
399 clnt_destroy(handle
->sm_clnt
);
400 DPRINTF1("Error in opening %s\n", smedia_service
);
401 PERROR(smedia_service
);
405 DPRINTF1("rbuf address=%p\n", rbuf
);
406 ddesc
[0].d_data
.d_desc
.d_descriptor
= fd
;
407 ddesc
[0].d_attributes
= DOOR_DESCRIPTOR
;
408 reqopen
.cnum
= SMEDIA_CNUM_OPEN_FD
;
409 door_args
.data_ptr
= (char *)&reqopen
;
410 door_args
.data_size
= sizeof (smedia_services_t
);
411 door_args
.desc_ptr
= &ddesc
[0];
412 door_args
.desc_num
= 1;
413 door_args
.rbuf
= rbuf
;
414 door_args
.rsize
= sizeof (rbuf
);
416 ret_val
= door_call(door_fd
, &door_args
);
417 (void) close(door_fd
);
419 (void) dlclose(handle
->sm_lib_handle
);
422 clnt_destroy(handle
->sm_clnt
);
426 DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
427 door_args
.rsize
, door_args
.data_size
,
429 reterror
= (smedia_reterror_t
*)((void *)door_args
.data_ptr
);
430 if (reterror
->cnum
!= SMEDIA_CNUM_OPEN_FD
) {
431 (void) dlclose(handle
->sm_lib_handle
);
434 clnt_destroy(handle
->sm_clnt
);
436 "*** door call failed *** cnum returned = 0x%x\n", reterror
->cnum
);
437 errno
= reterror
->errnum
;
441 * 2 door descriptors are returned after the above door call.
442 * The first door descriptor is the one that will be used
443 * in subsequent smedia calls. A dedicated thread is
444 * associated with this door to handle client calls.
445 * The second door descriptor is needed to signal unexpected
446 * death of the client to the server. This will help the server
447 * to do the necessary cleanup.
449 if (door_args
.desc_num
!= 2) {
450 (void) dlclose(handle
->sm_lib_handle
);
453 clnt_destroy(handle
->sm_clnt
);
454 DPRINTF("Num of door descriptors returned by "
456 if (door_args
.desc_num
)
457 (void) close(door_args
.desc_ptr
->\
458 d_data
.d_desc
.d_descriptor
);
461 door_server
= door_args
.desc_ptr
->d_data
.d_desc
.d_descriptor
;
462 /* Check if the descriptor returned is S_IFDOOR */
463 if (fstat(door_server
, &stat
) < 0) {
465 (void) dlclose(handle
->sm_lib_handle
);
468 clnt_destroy(handle
->sm_clnt
);
471 if (!S_ISDOOR(stat
.st_mode
)) {
473 "Descriptor returned by door_call is not of type DOOR\n");
474 (void) dlclose(handle
->sm_lib_handle
);
477 clnt_destroy(handle
->sm_clnt
);
480 handle
->sm_door
= door_server
;
482 door_args
.desc_ptr
++;
483 handle
->sm_death_door
=
484 door_args
.desc_ptr
->d_data
.d_desc
.d_descriptor
;
485 DPRINTF("door call succeeded.\n");
486 return ((smedia_handle_t
)handle
);
490 return ((smedia_handle_t
)handle
);