1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * l_misc.c : 31*0Sstevel@tonic-gate * This file contains the miscelleneous routines for libsm.so 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include <sys/types.h> 35*0Sstevel@tonic-gate #include <sys/stat.h> 36*0Sstevel@tonic-gate #include <sys/utsname.h> 37*0Sstevel@tonic-gate #include <fcntl.h> 38*0Sstevel@tonic-gate #include <sys/dkio.h> 39*0Sstevel@tonic-gate #include <sys/vtoc.h> 40*0Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 41*0Sstevel@tonic-gate #include <dirent.h> 42*0Sstevel@tonic-gate #include <dlfcn.h> 43*0Sstevel@tonic-gate #include <stdlib.h> 44*0Sstevel@tonic-gate #include <sys/stat.h> 45*0Sstevel@tonic-gate #include <strings.h> 46*0Sstevel@tonic-gate #include "l_defines.h" 47*0Sstevel@tonic-gate #include <rpc/rpc.h> 48*0Sstevel@tonic-gate #include "smed.h" 49*0Sstevel@tonic-gate #include <sys/smedia.h> 50*0Sstevel@tonic-gate #include "../inc/rmedia.h" 51*0Sstevel@tonic-gate #include <smserver.h> 52*0Sstevel@tonic-gate #include <sys/mman.h> 53*0Sstevel@tonic-gate #include <utmpx.h> 54*0Sstevel@tonic-gate #include <limits.h> 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #ifdef _LP64 57*0Sstevel@tonic-gate #ifdef __sparc 58*0Sstevel@tonic-gate #define PATHNAME "/usr/lib/smedia/sparcv9" 59*0Sstevel@tonic-gate #else 60*0Sstevel@tonic-gate #define PATHNAME "/usr/lib/smedia/amd64" 61*0Sstevel@tonic-gate #endif 62*0Sstevel@tonic-gate #else 63*0Sstevel@tonic-gate #define PATHNAME "/usr/lib/smedia" 64*0Sstevel@tonic-gate #endif 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate #define PERROR(string) my_perror(gettext(string)) 67*0Sstevel@tonic-gate #define RUN_LIBSMEDIA_SERVER " /usr/lib/smedia/rpc.smserverd &\n" 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate static void 70*0Sstevel@tonic-gate my_perror(char *err_string) 71*0Sstevel@tonic-gate { 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate int error_no; 74*0Sstevel@tonic-gate if (errno == 0) 75*0Sstevel@tonic-gate return; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate error_no = errno; 78*0Sstevel@tonic-gate (void) fprintf(stderr, gettext(err_string)); 79*0Sstevel@tonic-gate (void) fprintf(stderr, gettext(" : ")); 80*0Sstevel@tonic-gate errno = error_no; 81*0Sstevel@tonic-gate perror(""); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate static int 85*0Sstevel@tonic-gate is_server_running(rmedia_handle_t *handle) 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate door_arg_t door_args; 88*0Sstevel@tonic-gate smedia_reqping_t reqping; 89*0Sstevel@tonic-gate smedia_retping_t *retping; 90*0Sstevel@tonic-gate int ret_val; 91*0Sstevel@tonic-gate int door_fd; 92*0Sstevel@tonic-gate CLIENT *clnt; 93*0Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)]; 94*0Sstevel@tonic-gate smserver_info *server_info; 95*0Sstevel@tonic-gate struct utsname uts; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate * We will assume that we are running at level 2 or greater 99*0Sstevel@tonic-gate * and attempt to contact the server using RPC mecahnisms. 100*0Sstevel@tonic-gate * If that fails then we will attempt to contact the server 101*0Sstevel@tonic-gate * using non-rpc mechanism. This will enable the libsmedia 102*0Sstevel@tonic-gate * to be used in SINGLE user mode when inetd is not running. 103*0Sstevel@tonic-gate * We expect the server to have been started manually by user. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate (void) uname(&uts); 107*0Sstevel@tonic-gate clnt = clnt_create(uts.nodename, SMSERVERPROG, SMSERVERVERS, NULL); 108*0Sstevel@tonic-gate if (clnt == (CLIENT *)NULL) { 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * The failure could be that we are running at level 1 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate door_fd = open(smedia_service, O_RDONLY, 0644); 113*0Sstevel@tonic-gate if (door_fd < 0) { 114*0Sstevel@tonic-gate DPRINTF1("Error in opening %s\n", 115*0Sstevel@tonic-gate smedia_service); 116*0Sstevel@tonic-gate return (0); 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate DPRINTF1("rbuf address=%p\n", rbuf); 120*0Sstevel@tonic-gate reqping.cnum = SMEDIA_CNUM_PING; 121*0Sstevel@tonic-gate door_args.data_ptr = (char *)&reqping; 122*0Sstevel@tonic-gate door_args.data_size = sizeof (smedia_services_t); 123*0Sstevel@tonic-gate door_args.desc_ptr = NULL; 124*0Sstevel@tonic-gate door_args.desc_num = 0; 125*0Sstevel@tonic-gate door_args.rbuf = rbuf; 126*0Sstevel@tonic-gate door_args.rsize = sizeof (rbuf); 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate ret_val = door_call(door_fd, &door_args); 129*0Sstevel@tonic-gate (void) close(door_fd); 130*0Sstevel@tonic-gate if (ret_val < 0) { 131*0Sstevel@tonic-gate return (0); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n", 134*0Sstevel@tonic-gate door_args.rsize, door_args.data_size, 135*0Sstevel@tonic-gate door_args.data_ptr); 136*0Sstevel@tonic-gate retping = (smedia_retping_t *)( 137*0Sstevel@tonic-gate (void *)door_args.data_ptr); 138*0Sstevel@tonic-gate if (retping->cnum != SMEDIA_CNUM_PING) { 139*0Sstevel@tonic-gate DPRINTF1( 140*0Sstevel@tonic-gate "*** door call failed *** cnum returned = 0x%x\n", retping->cnum); 141*0Sstevel@tonic-gate return (0); 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate return (1); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate server_info = smserverproc_get_serverinfo_1(NULL, clnt); 146*0Sstevel@tonic-gate if (server_info == NULL) { 147*0Sstevel@tonic-gate if (clnt) 148*0Sstevel@tonic-gate clnt_destroy(clnt); 149*0Sstevel@tonic-gate return (0); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate if (server_info->status != 0) { 152*0Sstevel@tonic-gate if (clnt) 153*0Sstevel@tonic-gate clnt_destroy(clnt); 154*0Sstevel@tonic-gate DPRINTF1( 155*0Sstevel@tonic-gate "get server_info call failed. status = %d\n", 156*0Sstevel@tonic-gate server_info->status); 157*0Sstevel@tonic-gate return (0); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate if (server_info->vernum != SMSERVERVERS) { 160*0Sstevel@tonic-gate if (clnt) 161*0Sstevel@tonic-gate clnt_destroy(clnt); 162*0Sstevel@tonic-gate DPRINTF2( 163*0Sstevel@tonic-gate "version expected = %d version returned = %d\n", 164*0Sstevel@tonic-gate SMSERVERVERS, server_info->vernum); 165*0Sstevel@tonic-gate return (0); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate door_fd = open(smedia_service, O_RDONLY, 0644); 169*0Sstevel@tonic-gate if (door_fd < 0) { 170*0Sstevel@tonic-gate DPRINTF1("Error in opening %s\n", smedia_service); 171*0Sstevel@tonic-gate return (0); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate DPRINTF1("rbuf address=%p\n", rbuf); 175*0Sstevel@tonic-gate reqping.cnum = SMEDIA_CNUM_PING; 176*0Sstevel@tonic-gate door_args.data_ptr = (char *)&reqping; 177*0Sstevel@tonic-gate door_args.data_size = sizeof (smedia_services_t); 178*0Sstevel@tonic-gate door_args.desc_ptr = NULL; 179*0Sstevel@tonic-gate door_args.desc_num = 0; 180*0Sstevel@tonic-gate door_args.rbuf = rbuf; 181*0Sstevel@tonic-gate door_args.rsize = sizeof (rbuf); 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate ret_val = door_call(door_fd, &door_args); 184*0Sstevel@tonic-gate (void) close(door_fd); 185*0Sstevel@tonic-gate if (ret_val < 0) { 186*0Sstevel@tonic-gate return (0); 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n", 189*0Sstevel@tonic-gate door_args.rsize, door_args.data_size, 190*0Sstevel@tonic-gate door_args.data_ptr); 191*0Sstevel@tonic-gate retping = (smedia_retping_t *)((void *)door_args.data_ptr); 192*0Sstevel@tonic-gate if (retping->cnum != SMEDIA_CNUM_PING) { 193*0Sstevel@tonic-gate DPRINTF1( 194*0Sstevel@tonic-gate "*** door call failed *** cnum returned = 0x%x\n", retping->cnum); 195*0Sstevel@tonic-gate return (0); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate handle->sm_clnt = clnt; 198*0Sstevel@tonic-gate return (1); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate static void * 202*0Sstevel@tonic-gate get_dev_library_handle(int32_t fd) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate void *handle; 205*0Sstevel@tonic-gate void *old_handle = NULL; 206*0Sstevel@tonic-gate struct dk_cinfo dkinfo; 207*0Sstevel@tonic-gate DIR *dirp; 208*0Sstevel@tonic-gate struct dirent *dp; 209*0Sstevel@tonic-gate char *pathname; 210*0Sstevel@tonic-gate int32_t (*d_fcn_ptr)(ushort_t, ushort_t); 211*0Sstevel@tonic-gate int32_t (*v_fcn_ptr)(void); 212*0Sstevel@tonic-gate int32_t ret_val; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 215*0Sstevel@tonic-gate PERROR("DKIOCINFO failed"); 216*0Sstevel@tonic-gate return (NULL); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate DPRINTF1("dki_ctype = 0x%x\n", dkinfo.dki_ctype); 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if ((pathname = malloc(PATH_MAX)) == NULL) { 221*0Sstevel@tonic-gate PERROR("malloc failed"); 222*0Sstevel@tonic-gate return (NULL); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate dirp = opendir(PATHNAME); 226*0Sstevel@tonic-gate if (dirp == NULL) { 227*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Couldnot open %s\n"), PATHNAME); 228*0Sstevel@tonic-gate free(pathname); 229*0Sstevel@tonic-gate return (NULL); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 233*0Sstevel@tonic-gate if (strncmp("sm_", dp->d_name, 3) != 0) { 234*0Sstevel@tonic-gate DPRINTF1("not a library %s\n", dp->d_name); 235*0Sstevel@tonic-gate continue; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate if (snprintf(pathname, PATH_MAX, "%s/%s", 238*0Sstevel@tonic-gate PATHNAME, dp->d_name) >= PATH_MAX) { 239*0Sstevel@tonic-gate continue; 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate handle = dlopen(pathname, RTLD_LAZY); 243*0Sstevel@tonic-gate if (handle == NULL) { 244*0Sstevel@tonic-gate PERROR("Error opening library file"); 245*0Sstevel@tonic-gate continue; 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate d_fcn_ptr = (int32_t (*)(ushort_t, ushort_t))dlsym(handle, 248*0Sstevel@tonic-gate "_m_device_type"); 249*0Sstevel@tonic-gate if (d_fcn_ptr == NULL) { 250*0Sstevel@tonic-gate DPRINTF("Could not find _m_device_type\n"); 251*0Sstevel@tonic-gate (void) dlclose(handle); 252*0Sstevel@tonic-gate continue; 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate ret_val = (*d_fcn_ptr)(dkinfo.dki_ctype, 0); 255*0Sstevel@tonic-gate if (ret_val == 0) { 256*0Sstevel@tonic-gate DPRINTF1("NAME %s\n", dp->d_name); 257*0Sstevel@tonic-gate v_fcn_ptr = (int32_t (*)(void))dlsym(handle, 258*0Sstevel@tonic-gate "_m_version_no"); 259*0Sstevel@tonic-gate if (v_fcn_ptr == NULL) { 260*0Sstevel@tonic-gate DPRINTF("Could not find _m_version_no\n"); 261*0Sstevel@tonic-gate (void) dlclose(handle); 262*0Sstevel@tonic-gate continue; 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate ret_val = (*v_fcn_ptr)(); 265*0Sstevel@tonic-gate if ((ret_val >= 0) && 266*0Sstevel@tonic-gate (ret_val >= SM_PLUGIN_VERSION)) { 267*0Sstevel@tonic-gate if (old_handle != NULL) 268*0Sstevel@tonic-gate (void) dlclose(old_handle); 269*0Sstevel@tonic-gate old_handle = handle; 270*0Sstevel@tonic-gate continue; 271*0Sstevel@tonic-gate } else { 272*0Sstevel@tonic-gate (void) dlclose(handle); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate } else { 275*0Sstevel@tonic-gate (void) dlclose(handle); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate free(pathname); 279*0Sstevel@tonic-gate (void) closedir(dirp); 280*0Sstevel@tonic-gate return (old_handle); 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate int32_t 284*0Sstevel@tonic-gate call_function(rmedia_handle_t *handle, void *ip, char *func_name) 285*0Sstevel@tonic-gate { 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate int32_t ret_val; 288*0Sstevel@tonic-gate int32_t (*fcn_ptr)(rmedia_handle_t *handle, void *ip); 289*0Sstevel@tonic-gate void *lib_handle; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate if (handle == NULL) { 292*0Sstevel@tonic-gate DPRINTF("Handle is NULL\n"); 293*0Sstevel@tonic-gate errno = EINVAL; 294*0Sstevel@tonic-gate return (-1); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate lib_handle = handle->sm_lib_handle; 297*0Sstevel@tonic-gate if (handle->sm_signature != LIBSMEDIA_SIGNATURE) { 298*0Sstevel@tonic-gate DPRINTF2("call_function:signature expected=0x%x, found=0x%x\n", 299*0Sstevel@tonic-gate LIBSMEDIA_SIGNATURE, handle->sm_signature); 300*0Sstevel@tonic-gate errno = EINVAL; 301*0Sstevel@tonic-gate return (-1); 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate fcn_ptr = (int32_t (*)(rmedia_handle_t *, void*)) 305*0Sstevel@tonic-gate dlsym(lib_handle, func_name); 306*0Sstevel@tonic-gate if (fcn_ptr == NULL) { 307*0Sstevel@tonic-gate DPRINTF1("Could not find %s\n", func_name); 308*0Sstevel@tonic-gate errno = ENOTSUP; 309*0Sstevel@tonic-gate return (-1); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate ret_val = (*fcn_ptr)(handle, ip); 312*0Sstevel@tonic-gate return (ret_val); 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate int32_t 316*0Sstevel@tonic-gate release_handle(rmedia_handle_t *handle) 317*0Sstevel@tonic-gate { 318*0Sstevel@tonic-gate if (handle == NULL) { 319*0Sstevel@tonic-gate DPRINTF("Handle is NULL\n"); 320*0Sstevel@tonic-gate errno = EINVAL; 321*0Sstevel@tonic-gate return (-1); 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate if ((handle->sm_dkinfo.dki_ctype == DKC_SCSI_CCS) || 324*0Sstevel@tonic-gate (handle->sm_dkinfo.dki_ctype == DKC_MD21) || 325*0Sstevel@tonic-gate (handle->sm_dkinfo.dki_ctype == DKC_CDROM)) { 326*0Sstevel@tonic-gate (void) close(handle->sm_door); 327*0Sstevel@tonic-gate (void) close(handle->sm_death_door); 328*0Sstevel@tonic-gate if (handle->sm_buf != NULL) 329*0Sstevel@tonic-gate (void) munmap(handle->sm_buf, handle->sm_bufsize); 330*0Sstevel@tonic-gate if (handle->sm_clnt != NULL) 331*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate (void) close(handle->sm_buffd); 334*0Sstevel@tonic-gate handle->sm_signature = 0; 335*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 336*0Sstevel@tonic-gate free(handle); 337*0Sstevel@tonic-gate return (0); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate smedia_handle_t 341*0Sstevel@tonic-gate get_handle_from_fd(int32_t fd) 342*0Sstevel@tonic-gate { 343*0Sstevel@tonic-gate rmedia_handle_t *handle; 344*0Sstevel@tonic-gate void *lib_handle; 345*0Sstevel@tonic-gate int door_fd, door_server; 346*0Sstevel@tonic-gate int ret_val; 347*0Sstevel@tonic-gate door_arg_t door_args; 348*0Sstevel@tonic-gate smedia_reqopen_t reqopen; 349*0Sstevel@tonic-gate smedia_reterror_t *reterror; 350*0Sstevel@tonic-gate door_desc_t ddesc[2]; 351*0Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)]; 352*0Sstevel@tonic-gate struct stat stat; 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate DPRINTF("smedia_get_handle called\n"); 355*0Sstevel@tonic-gate handle = (rmedia_handle_t *)malloc(sizeof (rmedia_handle_t)); 356*0Sstevel@tonic-gate if (handle == NULL) { 357*0Sstevel@tonic-gate DPRINTF("Could not allocate memory for handle\n"); 358*0Sstevel@tonic-gate return (NULL); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate (void) memset((void *) handle, 0, sizeof (rmedia_handle_t)); 361*0Sstevel@tonic-gate handle->sm_fd = -1; 362*0Sstevel@tonic-gate handle->sm_door = -1; 363*0Sstevel@tonic-gate handle->sm_death_door = -1; 364*0Sstevel@tonic-gate handle->sm_buffd = -1; 365*0Sstevel@tonic-gate handle->sm_buf = NULL; 366*0Sstevel@tonic-gate handle->sm_bufsize = 0; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &handle->sm_dkinfo) == -1) { 369*0Sstevel@tonic-gate free(handle); 370*0Sstevel@tonic-gate PERROR("DKIOCINFO failed"); 371*0Sstevel@tonic-gate return (NULL); 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate lib_handle = get_dev_library_handle(fd); 374*0Sstevel@tonic-gate if (lib_handle == NULL) { 375*0Sstevel@tonic-gate free(handle); 376*0Sstevel@tonic-gate DPRINTF("lib_Handle is NULL\n"); 377*0Sstevel@tonic-gate errno = ENOTSUP; 378*0Sstevel@tonic-gate return (NULL); 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate DPRINTF("Handle initialised successfully.\n"); 381*0Sstevel@tonic-gate /* Initialise the handle elements */ 382*0Sstevel@tonic-gate handle->sm_lib_handle = lib_handle; 383*0Sstevel@tonic-gate handle->sm_signature = LIBSMEDIA_SIGNATURE; 384*0Sstevel@tonic-gate DPRINTF2("fd=%d signature=0x%x\n", handle->sm_fd, handle->sm_signature); 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate if ((handle->sm_dkinfo.dki_ctype == DKC_SCSI_CCS) || 387*0Sstevel@tonic-gate (handle->sm_dkinfo.dki_ctype == DKC_MD21) || 388*0Sstevel@tonic-gate (handle->sm_dkinfo.dki_ctype == DKC_CDROM)) { 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate ret_val = is_server_running(handle); 391*0Sstevel@tonic-gate if (ret_val == 0) { 392*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 393*0Sstevel@tonic-gate free(handle); 394*0Sstevel@tonic-gate return (NULL); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate door_fd = open(smedia_service, O_RDONLY, 0644); 397*0Sstevel@tonic-gate if (door_fd < 0) { 398*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 399*0Sstevel@tonic-gate free(handle); 400*0Sstevel@tonic-gate if (handle->sm_clnt) 401*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 402*0Sstevel@tonic-gate DPRINTF1("Error in opening %s\n", smedia_service); 403*0Sstevel@tonic-gate PERROR(smedia_service); 404*0Sstevel@tonic-gate return (NULL); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate DPRINTF1("rbuf address=%p\n", rbuf); 408*0Sstevel@tonic-gate ddesc[0].d_data.d_desc.d_descriptor = fd; 409*0Sstevel@tonic-gate ddesc[0].d_attributes = DOOR_DESCRIPTOR; 410*0Sstevel@tonic-gate reqopen.cnum = SMEDIA_CNUM_OPEN_FD; 411*0Sstevel@tonic-gate door_args.data_ptr = (char *)&reqopen; 412*0Sstevel@tonic-gate door_args.data_size = sizeof (smedia_services_t); 413*0Sstevel@tonic-gate door_args.desc_ptr = &ddesc[0]; 414*0Sstevel@tonic-gate door_args.desc_num = 1; 415*0Sstevel@tonic-gate door_args.rbuf = rbuf; 416*0Sstevel@tonic-gate door_args.rsize = sizeof (rbuf); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate ret_val = door_call(door_fd, &door_args); 419*0Sstevel@tonic-gate (void) close(door_fd); 420*0Sstevel@tonic-gate if (ret_val < 0) { 421*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 422*0Sstevel@tonic-gate free(handle); 423*0Sstevel@tonic-gate if (handle->sm_clnt) 424*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 425*0Sstevel@tonic-gate PERROR("door_call"); 426*0Sstevel@tonic-gate return (NULL); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n", 429*0Sstevel@tonic-gate door_args.rsize, door_args.data_size, 430*0Sstevel@tonic-gate door_args.data_ptr); 431*0Sstevel@tonic-gate reterror = (smedia_reterror_t *)((void *)door_args.data_ptr); 432*0Sstevel@tonic-gate if (reterror->cnum != SMEDIA_CNUM_OPEN_FD) { 433*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 434*0Sstevel@tonic-gate free(handle); 435*0Sstevel@tonic-gate if (handle->sm_clnt) 436*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 437*0Sstevel@tonic-gate DPRINTF1( 438*0Sstevel@tonic-gate "*** door call failed *** cnum returned = 0x%x\n", reterror->cnum); 439*0Sstevel@tonic-gate errno = reterror->errnum; 440*0Sstevel@tonic-gate return (NULL); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate /* 443*0Sstevel@tonic-gate * 2 door descriptors are returned after the above door call. 444*0Sstevel@tonic-gate * The first door descriptor is the one that will be used 445*0Sstevel@tonic-gate * in subsequent smedia calls. A dedicated thread is 446*0Sstevel@tonic-gate * associated with this door to handle client calls. 447*0Sstevel@tonic-gate * The second door descriptor is needed to signal unexpected 448*0Sstevel@tonic-gate * death of the client to the server. This will help the server 449*0Sstevel@tonic-gate * to do the necessary cleanup. 450*0Sstevel@tonic-gate */ 451*0Sstevel@tonic-gate if (door_args.desc_num != 2) { 452*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 453*0Sstevel@tonic-gate free(handle); 454*0Sstevel@tonic-gate if (handle->sm_clnt) 455*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 456*0Sstevel@tonic-gate DPRINTF( 457*0Sstevel@tonic-gate "Num of door descriptors returned by server is not 2"); 458*0Sstevel@tonic-gate if (door_args.desc_num) 459*0Sstevel@tonic-gate (void) close( 460*0Sstevel@tonic-gate door_args.desc_ptr->d_data.d_desc.d_descriptor); 461*0Sstevel@tonic-gate return (NULL); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate door_server = door_args.desc_ptr->d_data.d_desc.d_descriptor; 464*0Sstevel@tonic-gate /* Check if the descriptor returned is S_IFDOOR */ 465*0Sstevel@tonic-gate if (fstat(door_server, &stat) < 0) { 466*0Sstevel@tonic-gate PERROR("fstat"); 467*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 468*0Sstevel@tonic-gate free(handle); 469*0Sstevel@tonic-gate if (handle->sm_clnt) 470*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 471*0Sstevel@tonic-gate return (NULL); 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate if ((stat.st_mode & S_IFDOOR) != S_IFDOOR) { 474*0Sstevel@tonic-gate DPRINTF( 475*0Sstevel@tonic-gate "Descriptor returned by door_call is not of type DOOR\n"); 476*0Sstevel@tonic-gate (void) dlclose(handle->sm_lib_handle); 477*0Sstevel@tonic-gate free(handle); 478*0Sstevel@tonic-gate if (handle->sm_clnt) 479*0Sstevel@tonic-gate clnt_destroy(handle->sm_clnt); 480*0Sstevel@tonic-gate return (NULL); 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate handle->sm_door = door_server; 483*0Sstevel@tonic-gate handle->sm_fd = fd; 484*0Sstevel@tonic-gate door_args.desc_ptr++; 485*0Sstevel@tonic-gate handle->sm_death_door = 486*0Sstevel@tonic-gate door_args.desc_ptr->d_data.d_desc.d_descriptor; 487*0Sstevel@tonic-gate DPRINTF("door call succeeded.\n"); 488*0Sstevel@tonic-gate return ((smedia_handle_t)handle); 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate } else { 491*0Sstevel@tonic-gate handle->sm_fd = fd; 492*0Sstevel@tonic-gate return ((smedia_handle_t)handle); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate } 496