Home | History | Annotate | Download | only in common
      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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     22  * Use is subject to license terms.
     23  */
     24 
     25 
     26 #include <limits.h>
     27 #include <pthread.h>
     28 #include <synch.h>
     29 #include <sys/types.h>
     30 #include <sys/wait.h>
     31 #include <sys/stat.h>
     32 #include <sys/mkdev.h>
     33 #include <dirent.h>
     34 #include <netdb.h>
     35 #include <syslog.h>
     36 #include <ctype.h>
     37 #include <signal.h>
     38 #include <sys/time.h>
     39 #include <unistd.h>
     40 #include <stropts.h>
     41 #include <fcntl.h>
     42 #include <strings.h>
     43 #include <errno.h>
     44 #include <stdlib.h>
     45 #include <stdio.h>
     46 #include <dlfcn.h>
     47 #include <link.h>
     48 #include <netdb.h>
     49 #include <sys/scsi/impl/uscsi.h>
     50 #include <sys/scsi/generic/sense.h>
     51 #include <sys/scsi/generic/status.h>
     52 #include <sys/mtio.h>
     53 #include <sys/param.h>
     54 #include <libgen.h>
     55 #include <mms_list.h>
     56 #include <mms_parser.h>
     57 #include <dmd_impl.h>
     58 #include <dm_impl.h>
     59 #include <mms_network.h>
     60 #include <dm_drive.h>
     61 #include <mms_sym.h>
     62 #include <dm_msg.h>
     63 #include <mms_trace.h>
     64 #include <mms_dmd.h>
     65 #include <dm_proto.h>
     66 #include <host_ident.h>
     67 #include <mms_strapp.h>
     68 #include <mms_cores.h>
     69 #include <mms_cat.h>
     70 
     71 static char	*_SrcFile = __FILE__;
     72 
     73 static int		dm_debug = MMS_SEV_DEVP;	/* DM's default */
     74 static int		dm_caught_usr1 = 0;
     75 static int		dm_caught_usr2 = 0;
     76 static int		dm_caught_term = 0;
     77 static int		dm_caught_int = 0;
     78 static dm_wka_t		dm_wka;
     79 static drv_drive_t	drv_drv;
     80 static drv_jtab_t	drv_jtab;
     81 static drv_mount_t	drv_mount;
     82 static drv_scsi_err_t	drv_scsi_err;
     83 static uchar_t		drv_iobuf[DRV_IOBUF_LEN];
     84 static drv_cart_access_t drv_dca;
     85 
     86 dm_wka_t		*wka = &dm_wka;
     87 drv_jtab_t		*jtab = &drv_jtab;
     88 drv_mount_t		*mnt = &drv_mount;
     89 drv_drive_t		*drv = &drv_drv;
     90 drv_scsi_err_t		*serr = &drv_scsi_err;
     91 drv_cart_access_t 	*dca = &drv_dca;
     92 mms_list_t		dm_msg_hdr_list;
     93 
     94 /*
     95  * Function name
     96  *	dm_init_log(void)
     97  *
     98  * Parameters:
     99  *	none
    100  *
    101  * Description:
    102  *	open a trace file for DM.
    103  *
    104  * Note:
    105  *
    106  *
    107  */
    108 void
    109 dm_init_log(void)
    110 {
    111 	char		*trfile;
    112 
    113 	trfile = mms_strnew("%s/%s.debug", DM_TRACE_DIR, DMNAME);
    114 	if (mms_trace_open(trfile, MMS_ID_DM, dm_debug, -1, 1, 1)) {
    115 		syslog(LOG_NOTICE, "Unable to open mms_trace file \"%s\"",
    116 		    trfile);
    117 	}
    118 	free(trfile);
    119 }
    120 
    121 /*
    122  * Function name
    123  *	dm_init_wka
    124  *
    125  * Parameters:
    126  *	none
    127  *
    128  * Description:
    129  *	initialize work area.
    130  *	The work area hold objects needed by DM, including mutexes,
    131  *	condition variables, lists pointers, etc.
    132  *
    133  * Return code:
    134  *	none
    135  *
    136  * Note:
    137  *
    138  *
    139  */
    140 
    141 void
    142 dm_init_wka(void)
    143 {
    144 	memset(wka, 0, sizeof (dm_wka_t));
    145 	mms_list_create(&wka->dm_pend_ack_queue, sizeof (dm_command_t),
    146 	    offsetof(dm_command_t, cmd_next));
    147 	mms_list_create(&wka->dm_cmd_queue, sizeof (dm_command_t),
    148 	    offsetof(dm_command_t, cmd_next));
    149 
    150 	pthread_mutex_init(&wka->dm_io_mutex, NULL);
    151 	pthread_mutex_init(&wka->dm_worker_mutex, NULL);
    152 	pthread_mutex_init(&wka->dm_queue_mutex, NULL);
    153 	pthread_mutex_init(&wka->dm_tdv_close_mutex, NULL);
    154 
    155 	pthread_cond_init(&wka->dm_work_cv, NULL);
    156 	pthread_cond_init(&wka->dm_tdv_close_cv, NULL);
    157 	pthread_cond_init(&wka->dm_accept_cv, NULL);
    158 
    159 	wka->dm_pid = getpid();
    160 	gethostname(wka->dm_local_hostname, sizeof (wka->dm_local_hostname));
    161 
    162 	memset(drv, 0, sizeof (drv_drv));
    163 	memset(dca, 0, sizeof (drv_dca));
    164 	drv->drv_iobuf = drv_iobuf;
    165 	drv->drv_lbl_blksize = -1;
    166 	drv->drv_file_blksize = -1;
    167 	wka->dm_pwbuf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
    168 	if (wka->dm_pwbuf_size <= 0) {
    169 		wka->dm_pwbuf_size = 1024;
    170 	}
    171 	wka->dm_pwbuf = malloc(wka->dm_pwbuf_size);
    172 	TRACE((MMS_DEVP, "dm_init_wka: wka initialized"));
    173 }
    174 
    175 /*
    176  * Function name
    177  *	dm_init_dev_lib(void *hdl)
    178  *
    179  * Parameters:
    180  *	hdl	pointer to the handle of the shared library that was
    181  *		opened by dlopen and contains device
    182  *		dependent code.
    183  *
    184  * Description:
    185  *	This function fills in the jump table used by DM to call device
    186  *	dependent functions and the drive table that holds some device
    187  *	specific information.
    188  *	DM initializes device libraries twice. Firstthe default library which
    189  *	has all the default functions and information. Then the device
    190  *	specific library which has only device specific information.
    191  *	Anything in the device specific library replaces those of the
    192  * default library.
    193  *
    194  * Return code:
    195  *	none
    196  *
    197  * Note:
    198  *
    199  *
    200  */
    201 
    202 void
    203 dm_init_dev_lib(void *hdl, int init)
    204 {
    205 #define	DM_INIT_DRV(x, type) {						\
    206 		addr = dlsym(hdl, # x);					\
    207 		if (addr != NULL) {					\
    208 			drv->x = type addr;				\
    209 		} else if (init) {					\
    210 			drv->x = NULL;					\
    211 		}							\
    212 	}
    213 
    214 #define	DM_INIT_JTAB(x) {						\
    215 		addr = dlsym(hdl, # x);					\
    216 		if (addr != NULL) {					\
    217 			jtab->x = (x ## _t *)addr;			\
    218 		} else if (init) {					\
    219 			jtab->x = NULL;					\
    220 		}							\
    221 	}
    222 
    223 	void		*addr;
    224 
    225 	DM_INIT_DRV(drv_prsv_supported, (int *));
    226 	if (drv->drv_prsv_supported != NULL) {
    227 		if (*(drv->drv_prsv_supported) == 1) {
    228 			/* persistent reservation supported */
    229 			drv->drv_flags |= DRV_USE_PRSV;
    230 		} else {
    231 			drv->drv_flags &= ~DRV_USE_PRSV;
    232 		}
    233 	}
    234 
    235 	DM_INIT_DRV(drv_dev_dir, (char *));
    236 	DM_INIT_DRV(drv_density, (mms_sym_t *));
    237 	DM_INIT_DRV(drv_shape, (char **));
    238 	DM_INIT_DRV(drv_shape_den, (drv_shape_density_t *));
    239 	DM_INIT_DRV(drv_timeout, (drv_timeout_t *));
    240 	DM_INIT_DRV(drv_drive_type, (char *));
    241 	DM_INIT_DRV(drv_disallowed_cmds, (int *));
    242 	DM_INIT_DRV(drv_num_disallowed_cmds, (int *));
    243 	DM_INIT_DRV(drv_disallowed_ioctls, (int *));
    244 	DM_INIT_DRV(drv_num_disallowed_ioctls, (int *));
    245 	DM_INIT_DRV(drv_skaa_tab, (drv_skaa_t *));
    246 
    247 	/*
    248 	 * Fill the jump table with devlib functions
    249 	 */
    250 	DM_INIT_JTAB(drv_init_dev);
    251 	DM_INIT_JTAB(drv_get_statistics);
    252 	DM_INIT_JTAB(drv_get_density);
    253 	DM_INIT_JTAB(drv_set_density);
    254 	DM_INIT_JTAB(drv_mk_prsv_key);
    255 	DM_INIT_JTAB(drv_disallowed);
    256 	DM_INIT_JTAB(drv_rebind_target);
    257 	DM_INIT_JTAB(drv_get_drivetype);
    258 	DM_INIT_JTAB(drv_get_targ);
    259 	DM_INIT_JTAB(drv_set_blksize);
    260 	DM_INIT_JTAB(drv_get_blksize);
    261 	DM_INIT_JTAB(drv_read);
    262 	DM_INIT_JTAB(drv_write);
    263 	DM_INIT_JTAB(drv_get_capacity);
    264 	DM_INIT_JTAB(drv_get_avail_capacity);
    265 	DM_INIT_JTAB(drv_log_sense);
    266 	DM_INIT_JTAB(drv_read_attribute);
    267 	DM_INIT_JTAB(drv_bind_raw_dev);
    268 
    269 	/*
    270 	 * The following are functions to execute scsi commands
    271 	 */
    272 	DM_INIT_JTAB(drv_clrerr);
    273 	DM_INIT_JTAB(drv_proc_error);
    274 	DM_INIT_JTAB(drv_inquiry);
    275 	DM_INIT_JTAB(drv_req_sense);
    276 	DM_INIT_JTAB(drv_wtm);
    277 	DM_INIT_JTAB(drv_tur);
    278 	DM_INIT_JTAB(drv_load);
    279 	DM_INIT_JTAB(drv_unload);
    280 	DM_INIT_JTAB(drv_rewind);
    281 	DM_INIT_JTAB(drv_mode_sense);
    282 	DM_INIT_JTAB(drv_mode_select);
    283 	DM_INIT_JTAB(drv_seek);
    284 	DM_INIT_JTAB(drv_tell);
    285 	DM_INIT_JTAB(drv_fsf);
    286 	DM_INIT_JTAB(drv_bsf);
    287 	DM_INIT_JTAB(drv_fsb);
    288 	DM_INIT_JTAB(drv_bsb);
    289 	DM_INIT_JTAB(drv_eom);
    290 	DM_INIT_JTAB(drv_get_pos);
    291 	DM_INIT_JTAB(drv_mtgetpos);
    292 	DM_INIT_JTAB(drv_mtrestpos);
    293 	DM_INIT_JTAB(drv_locate);
    294 	DM_INIT_JTAB(drv_blk_limit);
    295 	DM_INIT_JTAB(drv_reserve);
    296 	DM_INIT_JTAB(drv_release);
    297 	DM_INIT_JTAB(drv_get_serial_num);
    298 	DM_INIT_JTAB(drv_prsv_register);
    299 	DM_INIT_JTAB(drv_prsv_reserve);
    300 	DM_INIT_JTAB(drv_prsv_release);
    301 	DM_INIT_JTAB(drv_prsv_clear);
    302 	DM_INIT_JTAB(drv_prsv_preempt);
    303 	DM_INIT_JTAB(drv_prsv_read_keys);
    304 	DM_INIT_JTAB(drv_prsv_read_rsv);
    305 	DM_INIT_JTAB(drv_get_write_protect);
    306 	DM_INIT_JTAB(drv_set_compression);
    307 }
    308 
    309 /*
    310  * Function name
    311  *	dm_load_default_lib(void)
    312  *
    313  * Parameters:
    314  *	none
    315  *
    316  * Description:
    317  *	loads the default library and initialize the jump table.
    318  *
    319  * Return code:
    320  *	0	success
    321  *	-1	failed
    322  *
    323  * Note:
    324  *
    325  *
    326  */
    327 
    328 int
    329 dm_load_default_lib(void)
    330 {
    331 	char		*libpath;
    332 
    333 	memset(jtab, 0, sizeof (drv_jtab_t));
    334 
    335 	/*
    336 	 * Load the default device library
    337 	 */
    338 	libpath = mms_strnew("%s/%s", DM_DEV_LIB_DIR, "libdm_default.so");
    339 	wka->dm_default_lib_hdl =
    340 	    dlopen(libpath, RTLD_NOW | RTLD_GLOBAL | RTLD_PARENT);
    341 	if (wka->dm_default_lib_hdl == NULL) {
    342 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    343 		    "default device library %s open error: %s",
    344 		    libpath, dlerror()));
    345 		free(libpath);
    346 		return (-1);
    347 	}
    348 
    349 	/* Init jtab with default lib */
    350 	dm_init_dev_lib(wka->dm_default_lib_hdl, 1);
    351 	wka->dm_flags |= DM_DFLT_LIB_LOADED;
    352 	TRACE((MMS_OPER, "device library %s initialized", libpath));
    353 	free(libpath);
    354 	return (0);
    355 }
    356 
    357 /*
    358  * Function name
    359  *	dm_load_devlib(void)
    360  *
    361  * Parameters:
    362  *	none
    363  *
    364  * Description:
    365  *	get the device type and dlopen the device dependent library.
    366  *	initialize jump table with it.
    367  *
    368  * Return code:
    369  *	0	success
    370  *	-1	error
    371  *
    372  * Note:
    373  *
    374  *
    375  */
    376 
    377 int
    378 dm_load_devlib(void)
    379 {
    380 	char		*libpath;
    381 
    382 	/*
    383 	 * get device library name
    384 	 */
    385 	if (dm_get_dev_lib_name() != 0) {
    386 		return (-1);
    387 	}
    388 
    389 	libpath = mms_strnew("%s/%s", DM_DEV_LIB_DIR, wka->dm_dev_lib);
    390 	TRACE((MMS_DEVP, "Loading device library %s", libpath));
    391 	wka->dm_dev_lib_hdl =
    392 	    dlopen(libpath, RTLD_NOW | RTLD_GLOBAL | RTLD_PARENT);
    393 	if (wka->dm_dev_lib_hdl == NULL) {
    394 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    395 		    "dynamic library open error: %s", dlerror()));
    396 		free(libpath);
    397 		return (-1);
    398 	}
    399 
    400 	/* Init jtab with device lib */
    401 	dm_init_dev_lib(wka->dm_dev_lib_hdl, 0);
    402 	wka->dm_flags |= DM_DEV_LIB_LOADED;
    403 	dm_clear_dev();
    404 
    405 	TRACE((MMS_OPER, "device library %s initialized", libpath));
    406 	free(libpath);
    407 	return (0);
    408 
    409 }
    410 
    411 /*
    412  * Function name
    413  *	dm_read_cfg(char *cfgname)
    414  *
    415  * Parameters:
    416  *	pointer to config file name
    417  *
    418  * Description:
    419  *	read the confige file passed to DM on the command line.
    420  *	Parse it and collect specified values.
    421  *
    422  * Return code:
    423  *	0	success
    424  *	-1	error
    425  *
    426  * Note:
    427  *
    428  *
    429  */
    430 
    431 int
    432 dm_read_cfg(char *cfgname)
    433 {
    434 	int		fd;
    435 	struct	stat	statbuf;
    436 	char		*buf;
    437 	int		i;
    438 	mms_par_node_t	*cfg;
    439 	mms_par_node_t	*node;
    440 	mms_par_node_t	*val;
    441 	mms_par_err_t	*err;
    442 	mms_list_t		err_list;
    443 	char		*kw;
    444 
    445 	fd = open(cfgname, O_RDONLY);
    446 	if (fd < 0) {
    447 		syslog(LOG_ERR, "Unable to open DM config file %s: %s\n",
    448 		    cfgname, strerror(errno));
    449 		DM_EXIT(DM_NO_RESTART);
    450 	}
    451 
    452 	/*
    453 	 * Allocate a buffer to read in the entire config file
    454 	 */
    455 	if (fstat(fd, &statbuf)) {
    456 		syslog(LOG_ERR, "Unable to stat DM config file %s: %s\n",
    457 		    cfgname, strerror(errno));
    458 		DM_EXIT(DM_NO_RESTART);
    459 	}
    460 	buf = malloc(statbuf.st_size + 1);
    461 	if (buf == NULL) {
    462 		syslog(LOG_ERR, "Unable to alloc buffer for "
    463 		    "DM config file %s: %s\n", cfgname, strerror(errno));
    464 		DM_EXIT(DM_NO_RESTART);
    465 	}
    466 
    467 	/*
    468 	 * Read in config file
    469 	 */
    470 	i = read(fd, buf, statbuf.st_size);
    471 	if (i < 0) {
    472 		syslog(LOG_ERR, "Unable to read DM config file %s: %s\n",
    473 		    cfgname, strerror(errno));
    474 		DM_EXIT(DM_NO_RESTART);
    475 	}
    476 	buf[i] = '\0';
    477 
    478 	/*
    479 	 * Parse the config file
    480 	 */
    481 	i = mms_config_parse(&cfg, &err_list, buf);
    482 	if (i < 0) {
    483 		mms_list_foreach(&err_list, err) {
    484 			syslog(LOG_ERR,
    485 			    "line %d, col %d, near token %s, "
    486 			    "err code %d, %s\n",
    487 			    err->pe_line,
    488 			    err->pe_col,
    489 			    err->pe_token,
    490 			    err->pe_code, err->pe_msg);
    491 		}
    492 		syslog(LOG_ERR, "DM config file %s has errors\n", cfgname);
    493 		DM_EXIT(DM_NO_RESTART);
    494 	}
    495 	free(buf);
    496 
    497 	/*
    498 	 * Pick up the args
    499 	 */
    500 	MMS_PN_LOOKUP(node, cfg, kw = "host", MMS_PN_KEYWORD, NULL);
    501 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    502 	wka->dm_host = strdup(mms_pn_token(val));
    503 
    504 	MMS_PN_LOOKUP(node, cfg, kw = "port", MMS_PN_KEYWORD, NULL);
    505 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    506 	wka->dm_port = strdup(mms_pn_token(val));
    507 
    508 	MMS_PN_LOOKUP(node, cfg, kw = "name", MMS_PN_KEYWORD, NULL);
    509 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    510 	DRVNAME = strdup(mms_pn_token(val));
    511 
    512 	MMS_PN_LOOKUP(node, cfg, kw = "instance", MMS_PN_KEYWORD, NULL);
    513 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    514 	DMNAME = strdup(mms_pn_token(val));
    515 
    516 	MMS_PN_LOOKUP(node, cfg, kw = "password", MMS_PN_KEYWORD, NULL);
    517 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    518 	wka->dm_passwd = strdup(mms_pn_token(val));
    519 
    520 	if (node = mms_pn_lookup(cfg, kw = "mm_password",
    521 	    MMS_PN_KEYWORD, NULL)) {
    522 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    523 		wka->dm_mm_passwd = strdup(mms_pn_token(val));
    524 	}
    525 
    526 	if (node = mms_pn_lookup(cfg, kw = "ssl_enabled",
    527 	    MMS_PN_KEYWORD, NULL)) {
    528 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    529 		if (strcasecmp(mms_pn_token(val), "true") == 0)
    530 			wka->dm_ssl_enabled = 1;
    531 	}
    532 
    533 	if (node = mms_pn_lookup(cfg, kw = "ssl_cert_file",
    534 	    MMS_PN_KEYWORD, NULL)) {
    535 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    536 		wka->dm_ssl_cert_file = strdup(mms_pn_token(val));
    537 	}
    538 
    539 	if (node = mms_pn_lookup(cfg, kw = "ssl_pass",
    540 	    MMS_PN_KEYWORD, NULL)) {
    541 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    542 		wka->dm_ssl_pass = strdup(mms_pn_token(val));
    543 	}
    544 
    545 	if (node = mms_pn_lookup(cfg, kw = "ssl_pass_file",
    546 	    MMS_PN_KEYWORD, NULL)) {
    547 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    548 		wka->dm_ssl_pass_file = strdup(mms_pn_token(val));
    549 	}
    550 
    551 	if (node = mms_pn_lookup(cfg, kw = "ssl_crl_file",
    552 	    MMS_PN_KEYWORD, NULL)) {
    553 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    554 		wka->dm_ssl_crl_file = strdup(mms_pn_token(val));
    555 	}
    556 
    557 	if (node = mms_pn_lookup(cfg, kw = "ssl_peer_file",
    558 	    MMS_PN_KEYWORD, NULL)) {
    559 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    560 		wka->dm_ssl_peer_file = strdup(mms_pn_token(val));
    561 	}
    562 
    563 	if (node = mms_pn_lookup(cfg, kw = "ssl_cipher",
    564 	    MMS_PN_KEYWORD, NULL)) {
    565 		MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    566 		wka->dm_ssl_cipher = strdup(mms_pn_token(val));
    567 	}
    568 
    569 	MMS_PN_LOOKUP(node, cfg, kw = "path", MMS_PN_KEYWORD, NULL);
    570 	MMS_PN_LOOKUP(val, node, NULL, MMS_PN_STRING, NULL);
    571 	wka->dm_drm_path = strdup(mms_pn_token(val));
    572 
    573 	mms_pe_destroy(&err_list);
    574 	mms_pn_destroy(cfg);
    575 
    576 	return (0);
    577 
    578 not_found:
    579 	syslog(LOG_ERR, "Missing \"%s\" from DM config file %s\n", kw,
    580 	    cfgname);
    581 	DM_EXIT(DM_NO_RESTART);
    582 	return (0);
    583 }
    584 
    585 /*
    586  * Function name
    587  *	dm_ssl_cfg(void)
    588  *
    589  * Parameters:
    590  *	none
    591  *
    592  * Description:
    593  *	Configure SSL if it is enabled
    594  *
    595  * Return code:
    596  *	0	success
    597  *	DM_NO_RESTART	terminate DM if error
    598  *
    599  * Note:
    600  *
    601  *
    602  */
    603 
    604 static int
    605 dm_ssl_cfg(void)
    606 {
    607 	mms_network_cfg_t	net;
    608 	mms_err_t	err;
    609 	char		ebuf[MMS_EBUF_LEN];
    610 
    611 #ifdef	MMS_OPENSSL
    612 	if (wka->dm_ssl_enabled) {
    613 		memset(&net, 0, sizeof (mms_network_cfg_t));
    614 		net.ssl_enabled = wka->dm_ssl_enabled;
    615 		net.ssl_cert_file = wka->dm_ssl_cert_file;
    616 		net.ssl_pass = wka->dm_ssl_pass;
    617 		net.ssl_pass_file = wka->dm_ssl_pass_file;
    618 		net.ssl_crl_file = wka->dm_ssl_crl_file;
    619 		net.ssl_peer_file = wka->dm_ssl_peer_file;
    620 		net.ssl_cipher = wka->dm_ssl_cipher;
    621 		if (mms_ssl_client(&net, &wka->dm_ssl_data, &err)) {
    622 			mms_get_error_string(&err, ebuf, MMS_EBUF_LEN);
    623 			TRACE((MMS_ERR, "ssl init - %s", ebuf));
    624 			DM_EXIT(DM_NO_RESTART);
    625 		}
    626 	}
    627 #endif	/* MMS_OPENSSL */
    628 
    629 	return (0);
    630 }
    631 
    632 /*
    633  * Function name
    634  *	void dm_rem_old_handle(void)
    635  *
    636  * Parameters:
    637  *	none
    638  *
    639  * Description:
    640  *	deletes handles left over from the previous
    641  *	run.
    642  *
    643  * Return code:
    644  *	none
    645  *
    646  * Note:
    647  *
    648  *
    649  */
    650 
    651 void
    652 dm_rem_old_handle(void)
    653 {
    654 	DIR		*dirp;
    655 	struct	dirent  *dp;
    656 	int		len;
    657 	char		*hdl;
    658 	int		err;
    659 
    660 	TRACE((MMS_DEVP, "dm_rem_old_handle: Removing old handles"));
    661 	dirp = opendir(MMS_HDL_DIR);
    662 	if (dirp == NULL) {
    663 		err = errno;
    664 		TRACE((MMS_CRIT, "Unable to open handle directory %s: %s",
    665 		    MMS_HDL_DIR, strerror(err)));
    666 		/*
    667 		 * If directory doe not exist, then create one.
    668 		 */
    669 		if (err == ENOENT) {
    670 			TRACE((MMS_DEBUG, "Createing handle directory %s",
    671 			    MMS_HDL_DIR));
    672 			/*
    673 			 * create a directory named MMS_HDL_DIR,
    674 			 * with read, write, and search permissions for
    675 			 * owner and group, and with read and search
    676 			 * permissions for others.
    677 			 */
    678 			if (mkdirp(MMS_HDL_DIR, 0755)) {
    679 				/*
    680 				 * create handle directory error
    681 				 */
    682 				err = errno;
    683 				if (err == EEXIST) {
    684 					TRACE((MMS_DEBUG, "%s "
    685 					    "already created by another DM",
    686 					    MMS_HDL_DIR));
    687 					return;
    688 				}
    689 				TRACE((MMS_CRIT, "Unable to create handle "
    690 				    "directory %s: %s",
    691 				    MMS_HDL_DIR, strerror(err)));
    692 				DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    693 				    "Unable to create handle directory %s: %s",
    694 				    MMS_HDL_DIR, strerror(err)));
    695 				DM_MSG_SEND((DM_ADM_ERR, DM_6529_MSG,
    696 				    DM_MSG_REASON));
    697 				DM_EXIT(DM_NO_RESTART);
    698 			}
    699 			/*
    700 			 * Created new handle directoru
    701 			 */
    702 			TRACE((MMS_DEBUG, "created %s", MMS_HDL_DIR));
    703 			return;
    704 		}
    705 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    706 		    "Unable to open handle directory %s: %s",
    707 		    MMS_HDL_DIR, strerror(err)));
    708 		DM_MSG_SEND((DM_ADM_ERR, DM_6525_MSG, DM_MSG_REASON));
    709 		DM_EXIT(DM_NO_RESTART);
    710 	}
    711 
    712 	len = strlen(wka->dm_hdl_prefix);
    713 	while ((dp = readdir(dirp)) != NULL) {
    714 		if (strncmp(dp->d_name, wka->dm_hdl_prefix, len) == 0) {
    715 			/* found an old handle */
    716 			hdl = mms_strapp(NULL,
    717 			    "%s/%s", MMS_HDL_DIR, dp->d_name);
    718 			TRACE((MMS_DEVP,
    719 			    "dm_rem_old_handle: Removing handle %s",
    720 			    dp->d_name));
    721 			unlink(hdl);
    722 			free(hdl);
    723 		}
    724 	}
    725 	closedir(dirp);
    726 }
    727 
    728 /*
    729  * Function name
    730  *	dm_init(int argc, char **argv)
    731  *
    732  * Parameters:
    733  *	the command line arguments which is the pathname of
    734  *	the config file.
    735  *
    736  * Description:
    737  *	- close all files and reopen the std* files.
    738  *	- read config file
    739  *	- initialize log, wka and ssl
    740  *	- open the drm device
    741  *
    742  * Return code:
    743  *	0	success
    744  *	exit DM if error.
    745  *
    746  * Note:
    747  *
    748  *
    749  */
    750 
    751 /* ARGSUSED */
    752 int
    753 dm_init(int argc, char **argv)
    754 {
    755 	int		i;
    756 	int		retries = 0;
    757 	char		*corename;
    758 
    759 	TRACE((MMS_DEVP, "dm_init: Initializing DM"));
    760 
    761 	/*
    762 	 * Close all opened files.
    763 	 */
    764 	for (i = 0; i < OPEN_MAX; i++)
    765 		close(i);
    766 
    767 	/*
    768 	 * Direct stdin, stdout and stderr to /dev/null
    769 	 */
    770 	fopen("/dev/null", "r");
    771 	fopen("/dev/null", "w");
    772 	fopen("/dev/null", "w");
    773 
    774 	setsid();			/* become session leader */
    775 	umask(0);			/* clear file mode create mask */
    776 
    777 	/*
    778 	 * Init message catalog
    779 	 */
    780 	mms_cat_open();
    781 
    782 	/*
    783 	 * Initialize work area
    784 	 */
    785 	dm_init_wka();
    786 
    787 	/*
    788 	 * Read config file
    789 	 * Path of config file is argv[1]
    790 	 */
    791 	if (dm_read_cfg(argv[1])) {
    792 		DM_EXIT(DM_NO_RESTART);
    793 	}
    794 
    795 	/* Move to where core files will be placed */
    796 	if (mms_set_core(MMS_CORES_DIR, DMNAME)) {
    797 		TRACE((MMS_ERR, "dm_init: DM's core setup failed %s",
    798 		    strerror(errno)));
    799 	}
    800 
    801 	corename = mms_strnew("core.mmsdm.%s", DMNAME);
    802 	/* Check to see how many core files exist */
    803 	if (mms_man_cores(MMS_CORES_DIR, corename)) {
    804 		TRACE((MMS_ERR, "dm_init: DM's mms_man_cores failed %s",
    805 		    strerror(errno)));
    806 	}
    807 	free(corename);
    808 
    809 	/*
    810 	 * Init message logging
    811 	 */
    812 	dm_init_log();
    813 	TRACE((MMS_OPER, "dm_init: ******** Starting DM %s ********",
    814 	    DMNAME));
    815 
    816 	/*
    817 	 * Open the DM device
    818 	 */
    819 	wka->dm_drm_fd = -1;				/* not opened yet */
    820 	while (dm_open_dm_device() < 0) {
    821 		if (errno == EBUSY && retries <= DM_OPEN_RETRIES) {
    822 			/* device is still opened */
    823 			sleep(DM_OPEN_INTERVAL);
    824 			retries++;
    825 		}
    826 		TRACE((MMS_ERR, "Unable to open DM device: %s",
    827 		    strerror(errno)));
    828 		DM_EXIT(DM_NO_RESTART);
    829 	}
    830 
    831 	/*
    832 	 * Init ssl
    833 	 */
    834 	if (dm_ssl_cfg()) {
    835 		DM_EXIT(DM_NO_RESTART);
    836 	}
    837 
    838 	/*
    839 	 * Start session with SMM
    840 	 */
    841 	if (dm_init_session(0)) {
    842 		TRACE((MMS_CRIT, "Unable to start a session with SMM"));
    843 		DM_EXIT(DM_NO_RESTART);
    844 	}
    845 
    846 	return (0);
    847 }
    848 
    849 /*
    850  * Function name
    851  *	dm_get_dev_lib_name(void)
    852  *
    853  * Parameters:
    854  *	none
    855  *
    856  * Description:
    857  *	Get device dependent library name and save it in work area.
    858  *	Library name is constructed from the vendor and product ID's from
    859  *	the inquiry data like this:
    860  *	lib<vendor>-<product>.o
    861  *	where :
    862  *	<vendor> is the vendor id with trailing blanks removed and
    863  *		each remaining blank substituted with a '_' character.
    864  *	<product> is the product id with trailing blanks removed and
    865  *		each remaining blank substituted with a '_' character.
    866  *
    867  * Return code:
    868  *	0	success
    869  *	-1	error
    870  *
    871  * Note:
    872  *
    873  *
    874  */
    875 
    876 int
    877 dm_get_dev_lib_name(void)
    878 {
    879 	char		vendor[9];
    880 	char		prod[17];
    881 	int		i;
    882 
    883 	if (drv->drv_flags & DRV_FATAL) {
    884 		return (EIO);
    885 	}
    886 
    887 	/*
    888 	 * Read the inquiry data
    889 	 */
    890 	if (DRV_CALL(drv_get_drivetype, ())) {
    891 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
    892 		    "unable to get vendor and product ID: %s",
    893 		    strerror(errno)));
    894 		mms_trace_flush();
    895 		return (-1);
    896 	}
    897 
    898 	(void) strlcpy(vendor, drv->drv_vend, sizeof (vendor));
    899 	/* trim trailing blanks */
    900 	for (i = strlen(vendor) - 1; i >= 0 && vendor[i] == ' '; i--) {
    901 		vendor[i] = '\0';
    902 	}
    903 	(void) strlcpy(prod, drv->drv_prod, sizeof (prod));
    904 	for (i = strlen(prod) - 1; i >= 0 && prod[i] == ' '; i--) {
    905 		prod[i] = '\0';
    906 	}
    907 
    908 	/* Convert remaining blanks to '_' */
    909 	for (i = 0; vendor[i] != '\0'; i++) {
    910 		if (vendor[i] == ' ') {
    911 			vendor[i] = '_';
    912 		}
    913 	}
    914 	for (i = 0; prod[i] != '\0'; i++) {
    915 		if (prod[i] == ' ') {
    916 			prod[i] = '_';
    917 		}
    918 	}
    919 
    920 	wka->dm_dev_lib = mms_strnew("lib%s_%s.so", vendor, prod);
    921 	TRACE((MMS_INFO, "Device lib name = %s", wka->dm_dev_lib));
    922 	return (0);
    923 }
    924 
    925 /*
    926  * Function name
    927  *	dm_init_session(int retries)
    928  *
    929  * Parameters:
    930  *	number of retries
    931  *
    932  * Description:
    933  *	initialize a session with the Media Manager
    934  *	retry until success or until the number of retries is exceeded.
    935  *
    936  * Return code:
    937  *	fd		If a welcome response was received from MM, then
    938  *			this routine returns the file descriptor that the
    939  *			client will use to communicate with MM.
    940  *	MMS_ERROR	If an error occurred while processing or if an
    941  *			unwelcome response was receieved from MM.
    942  *
    943  *
    944  * Note:
    945  *
    946  *
    947  */
    948 
    949 int
    950 dm_init_session(int retries)
    951 {
    952 	int		rc;
    953 	mms_network_cfg_t	cfg;
    954 	int		err;
    955 	char		*tag = NULL;
    956 
    957 	TRACE((MMS_DEVP, "dm_init_session: Initializing session"));
    958 	/*
    959 	 * 0 retries means forever
    960 	 */
    961 	if (retries == 0) {
    962 		retries = 0x7fffffff;
    963 	}
    964 
    965 	memset(&cfg, 0, sizeof (mms_network_cfg_t));
    966 	cfg.cli_host = strdup(wka->dm_host);
    967 	cfg.cli_port = strdup(wka->dm_port);
    968 	cfg.cli_name = strdup(drv->drv_drvname);
    969 	cfg.cli_inst = strdup(drv->drv_dmname);
    970 	cfg.cli_lang = MMS_DMP_LANG;
    971 	cfg.cli_vers = MMS_DMP_VERSION;
    972 	cfg.cli_pass = strdup(wka->dm_passwd);
    973 	if (wka->dm_mm_passwd) {
    974 		cfg.mm_pass = strdup(wka->dm_mm_passwd);
    975 	}
    976 
    977 	for (; retries > 0; retries--) {
    978 		if ((rc = mms_mmconnect(&cfg, wka->dm_ssl_data,
    979 		    &wka->dm_mms_conn, &err, tag)) != 0) {
    980 			/*
    981 			 * Unable to connect to mm
    982 			 */
    983 			TRACE((MMS_WARN, "DM %s unable to connect "
    984 			    "to MM: %d: %s", DMNAME,
    985 			    err, mms_sym_code_to_str(err)));
    986 			if (retries > 1) {
    987 				wka->dm_flags |= DM_SILENT;
    988 				sleep(DM_CONNECT_INTERVAL);
    989 			} else {
    990 				break;
    991 			}
    992 		} else {
    993 			/*
    994 			 * Successfully connected to MM
    995 			 */
    996 			wka->dm_flags &= ~DM_SILENT;
    997 			wka->dm_flags |= DM_HAVE_SESSION;
    998 			TRACE((MMS_OPER, "dm_init_session: "
    999 			    "DM %s connected to MM on %s %s",
   1000 			    DMNAME, wka->dm_host, wka->dm_port));
   1001 			break;
   1002 		}
   1003 	}
   1004 
   1005 	return (rc);
   1006 }
   1007 
   1008 /*
   1009  * Signal catching functions
   1010  */
   1011 
   1012 /*
   1013  * Function name
   1014  *	dm_sigusr1(void)
   1015  *
   1016  * Parameters:
   1017  *	none
   1018  *
   1019  * Description:
   1020  *	SIGUSR1 catcher
   1021  *
   1022  * Return code:
   1023  *	none
   1024  *
   1025  * Note:
   1026  *
   1027  *
   1028  */
   1029 
   1030 void
   1031 dm_sigusr1(void)
   1032 {
   1033 	TRACE((MMS_DEVP, "dm_sigusr1: Caught SIGUSR1"));
   1034 	dm_caught_usr1 = 1;
   1035 }
   1036 
   1037 /*
   1038  * Function name
   1039  *	dm_sigusr2(void)
   1040  *
   1041  * Parameters:
   1042  *	none
   1043  *
   1044  * Description:
   1045  *	SIGUSR2 catcher
   1046  *
   1047  * Return code:
   1048  *	none
   1049  *
   1050  * Note:
   1051  *
   1052  *
   1053  */
   1054 
   1055 void
   1056 dm_sigusr2(void)
   1057 {
   1058 	TRACE((MMS_DEVP, "dm_sigusr2: Caught SIGUSR2"));
   1059 	dm_caught_usr2 = 1;
   1060 }
   1061 
   1062 
   1063 /*
   1064  * Function name
   1065  *	dm_sigint(void)
   1066  *
   1067  * Parameters:
   1068  *	void
   1069  *
   1070  * Description:
   1071  *	SIGINT catcher
   1072  *
   1073  * Return code:
   1074  *	none
   1075  *
   1076  * Note:
   1077  *
   1078  *
   1079  */
   1080 
   1081 void
   1082 dm_sigint(void)
   1083 {
   1084 	/*
   1085 	 * Terminate this drive manager
   1086 	 */
   1087 	TRACE((MMS_DEVP, "dm_sigint: Caught SIGINT"));
   1088 	mms_trace_flush();
   1089 	dm_caught_int = 1;
   1090 }
   1091 
   1092 /*
   1093  * Function name
   1094  *	dm_sigterm(void)
   1095  *
   1096  * Parameters:
   1097  *	none
   1098  *
   1099  * Description:
   1100  *	SIGTERM catcher
   1101  *
   1102  * Return code:
   1103  *	none
   1104  *
   1105  * Note:
   1106  *
   1107  *
   1108  */
   1109 
   1110 void
   1111 dm_sigterm(void)
   1112 {
   1113 	/*
   1114 	 * Terminate this drive manager
   1115 	 */
   1116 	TRACE((MMS_DEVP, "dm_sigterm: Caught SIGTERM"));
   1117 	mms_trace_flush();
   1118 	dm_caught_term = 1;
   1119 }
   1120 
   1121 /*
   1122  * Function name
   1123  *	dm_sighup(void)
   1124  *
   1125  * Parameters:
   1126  *	none
   1127  *
   1128  * Description:
   1129  *	SIGHUP catcher
   1130  *
   1131  * Return code:
   1132  *	none
   1133  *
   1134  * Note:
   1135  *
   1136  *
   1137  */
   1138 
   1139 void
   1140 dm_sighup(void)
   1141 {
   1142 	/*
   1143 	 * Ignore Sighup
   1144 	 */
   1145 	TRACE((MMS_DEVP, "dm_sighup: Caught SIGHUP"));
   1146 	mms_trace_flush();
   1147 	/* Ignore sighup */
   1148 }
   1149 
   1150 /*
   1151  * Function name
   1152  *	dm_signal(int sig, void (*handler) ())
   1153  *
   1154  * Parameters:
   1155  *	sig	signal number
   1156  *	handler	signal handler
   1157  *
   1158  * Description:
   1159  *	install signal handler
   1160  *
   1161  * Return code:
   1162  *	none	if success
   1163  *	exit	if error
   1164  *
   1165  * Note:
   1166  *
   1167  *
   1168  */
   1169 
   1170 void
   1171 dm_signal(int sig, void (*handler) ())
   1172 {
   1173 	/*
   1174 	 * Setup to catch signals
   1175 	 */
   1176 	struct	sigaction act, oact;
   1177 
   1178 	TRACE((MMS_DEVP, "dm_signal: Setting signal handler"));
   1179 	memset(&act, 0, sizeof (act));
   1180 	act.sa_sigaction = handler;
   1181 	sigemptyset(&act.sa_mask);
   1182 	act.sa_flags = 0;
   1183 	if (sig != SIGALRM) {
   1184 		/*
   1185 		 * Allow alarm signal to interrupt
   1186 		 */
   1187 		act.sa_flags |= SA_RESTART;
   1188 	}
   1189 	if (sigaction(sig, &act, &oact) < 0) {
   1190 		TRACE((MMS_ERR, "Can't set signal handler for "
   1191 		    "signal %d: %s", sig, strerror(errno)));
   1192 		DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL,
   1193 		    "Unable to set signal handler for "
   1194 		    "signal %d: %s", sig, strerror(errno)));
   1195 		DM_MSG_SEND((DM_ADM_ERR, DM_6525_MSG, DM_MSG_REASON));
   1196 		DM_EXIT(DM_NO_RESTART);
   1197 	}
   1198 }
   1199 
   1200 /*
   1201  * Function name
   1202  *	dm_setup_sig_handler(void)
   1203  *
   1204  * Parameters:
   1205  *	none
   1206  *
   1207  * Description:
   1208  *	setup to install all signal handlers
   1209  *
   1210  * Return code:
   1211  *	none
   1212  *
   1213  * Note:
   1214  *
   1215  *
   1216  */
   1217 
   1218 
   1219 void
   1220 dm_setup_sig_handler(void)
   1221 {
   1222 	/*
   1223 	 * Setup SIGTERM handler
   1224 	 * Terminate drive manager
   1225 	 */
   1226 	TRACE((MMS_DEVP, "dm_setup_sig_handler: Catching SIGTERM"));
   1227 	dm_signal(SIGTERM, dm_sigterm);
   1228 
   1229 	/*
   1230 	 * Setup SIGUSR1 handler
   1231 	 * Driver request
   1232 	 */
   1233 	TRACE((MMS_DEVP, "dm_setup_sig_handler: Catching SIGUSR1"));
   1234 	dm_signal(SIGUSR1, dm_sigusr1);
   1235 
   1236 	/*
   1237 	 * Setup SIGUSR2 handler
   1238 	 * tdv device closed
   1239 	 */
   1240 	TRACE((MMS_DEVP, "dm_setup_sig_handler: Catching SIGUSR2"));
   1241 	dm_signal(SIGUSR2, dm_sigusr2);
   1242 
   1243 	/*
   1244 	 * Setup SIGHUP handler
   1245 	 */
   1246 	TRACE((MMS_DEVP, "dm_setup_sig_handler: Catching SIGHUP"));
   1247 	dm_signal(SIGHUP, dm_sighup);
   1248 
   1249 	/*
   1250 	 * Setup SIGINT handler
   1251 	 */
   1252 	TRACE((MMS_DEVP, "dm_setup_sig_handler: Catching SIGINT"));
   1253 	dm_signal(SIGINT, dm_sigint);
   1254 }
   1255 
   1256 int
   1257 main(int argc, char **argv)
   1258 {
   1259 	sigset_t	new_mask;
   1260 	sigset_t	old_mask;
   1261 	pthread_t	tid;
   1262 	int		rc = 0;
   1263 	fd_set		fdset;
   1264 	timespec_t	*tvp;
   1265 	int		nfds;
   1266 	int		always = 1;
   1267 
   1268 	/*
   1269 	 * Initialize message
   1270 	 */
   1271 	mms_list_create(&dm_msg_hdr_list, sizeof (dm_msg_hdr_t),
   1272 	    offsetof(dm_msg_hdr_t, msg_next));
   1273 	dm_msg_create_hdr();
   1274 
   1275 	/*
   1276 	 * Init the drive manager
   1277 	 */
   1278 	if (dm_init(argc, argv)) {
   1279 		TRACE((MMS_ERR,
   1280 		    "Unable to initialize the drive manager\n"));
   1281 		DM_EXIT(DM_NO_RESTART);
   1282 	}
   1283 
   1284 	/*
   1285 	 * Create handle prefix
   1286 	 */
   1287 	wka->dm_hdl_prefix = mms_strapp(NULL,
   1288 	    "%s.%s.%s",
   1289 	    wka->dm_local_hostname, DMNAME, DRVNAME);
   1290 
   1291 	/*
   1292 	 * Setup to block signals DM cares about.
   1293 	 * This is inherited by the worker thread so that it will not
   1294 	 * be interrupted by signals.
   1295 	 */
   1296 	sigemptyset(&new_mask);
   1297 	sigaddset(&new_mask, SIGUSR1);
   1298 	sigaddset(&new_mask, SIGUSR2);
   1299 	sigaddset(&new_mask, SIGINT);
   1300 	sigaddset(&new_mask, SIGTERM);
   1301 	sigaddset(&new_mask, SIGHUP);
   1302 	pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
   1303 
   1304 	/*
   1305 	 * DM successfully started
   1306 	 */
   1307 	TRACE((MMS_OPER, "DM initialized: DMName = %s, DriveName = %s",
   1308 	    DMNAME, DRVNAME));
   1309 	/*
   1310 	 * Start processing threads.
   1311 	 */
   1312 	pthread_create(&tid, NULL, dm_worker, wka);
   1313 
   1314 	/*
   1315 	 * Setup signal handlers
   1316 	 */
   1317 	dm_setup_sig_handler();
   1318 
   1319 	/*
   1320 	 * Main loop
   1321 	 */
   1322 	while (always) {
   1323 
   1324 		/* wakeup worker thread to do work */
   1325 		pthread_mutex_lock(&wka->dm_worker_mutex);
   1326 		wka->dm_work_todo = 1;
   1327 		pthread_cond_broadcast(&wka->dm_work_cv);
   1328 		pthread_mutex_unlock(&wka->dm_worker_mutex);
   1329 
   1330 		/*
   1331 		 * Setup for pselect
   1332 		 */
   1333 		nfds = 0;
   1334 		if (wka->dm_flags & DM_HAVE_SESSION) {
   1335 			nfds = wka->dm_mms_conn.mms_fd + 1;
   1336 			FD_ZERO(&fdset);
   1337 			FD_SET(wka->dm_mms_conn.mms_fd, &fdset);
   1338 			tvp = NULL;
   1339 		}
   1340 
   1341 		/*
   1342 		 * pselect will unblock signals blocked earlier
   1343 		 */
   1344 		rc = pselect(nfds, &fdset, NULL, NULL, tvp, &old_mask);
   1345 
   1346 		if (dm_caught_term) {
   1347 			dm_caught_term = 0;
   1348 			TRACE((MMS_DEBUG, "DM exit: caught SIGTERM"));
   1349 			DM_EXIT(DM_NO_RESTART);
   1350 		}
   1351 
   1352 		if (dm_caught_int) {
   1353 			dm_caught_int = 0;
   1354 			TRACE((MMS_DEBUG, "DM restart: caught SIGINT"));
   1355 			DM_EXIT(DM_RESTART);
   1356 		}
   1357 
   1358 		if (dm_caught_usr2) {
   1359 			dm_caught_usr2 = 0;
   1360 			TRACE((MMS_DEBUG, "caught SIGUSR2: "
   1361 			    "Waking up waiting command"));
   1362 			pthread_mutex_lock(&wka->dm_tdv_close_mutex);
   1363 			pthread_cond_broadcast(&wka->dm_tdv_close_cv);
   1364 			pthread_mutex_unlock(&wka->dm_tdv_close_mutex);
   1365 		}
   1366 
   1367 		if (dm_caught_usr1) {
   1368 			dm_caught_usr1 = 0;
   1369 			dm_get_request();
   1370 		}
   1371 
   1372 		if (rc > 0) {
   1373 			/* Input pending */
   1374 			if (FD_ISSET(wka->dm_mms_conn.mms_fd, &fdset)) {
   1375 				/* Read input and put it on input list */
   1376 				dm_read_input();
   1377 			}
   1378 		}
   1379 
   1380 		/*
   1381 		 * If connection to MM is closed, try reconnect
   1382 		 */
   1383 		if ((wka->dm_flags & DM_HAVE_SESSION) == 0) {
   1384 			wka->dm_flags |= DM_SILENT;
   1385 			dm_restart_session();
   1386 			wka->dm_flags &= ~DM_SILENT;
   1387 		}
   1388 		if (wka->dm_flags & DM_HAVE_SESSION) {
   1389 			/* Try sending accept again */
   1390 			pthread_mutex_lock(&wka->dm_queue_mutex);
   1391 			if (!mms_list_empty(&wka->dm_pend_ack_queue)) {
   1392 				pthread_mutex_unlock(&wka->dm_queue_mutex);
   1393 				dm_accept_cmds();
   1394 				pthread_mutex_lock(&wka->dm_queue_mutex);
   1395 			}
   1396 			pthread_mutex_unlock(&wka->dm_queue_mutex);
   1397 		}
   1398 
   1399 	}
   1400 	return (0);
   1401 }
   1402 
   1403 /*
   1404  * Function name
   1405  *	dm_restart_session(void)
   1406  *
   1407  * Parameters:
   1408  *	none
   1409  *
   1410  * Description:
   1411  *	restart a session with MM if it was disconnected
   1412  *
   1413  * Return code:
   1414  *	none
   1415  *
   1416  * Note:
   1417  *
   1418  *
   1419  */
   1420 
   1421 void
   1422 dm_restart_session(void)
   1423 {
   1424 	TRACE((MMS_OPER, "dm_restart_session: Restarting session"));
   1425 	(void) dm_init_session(1);
   1426 }
   1427 
   1428 /*
   1429  * Function name
   1430  *	dm_worker(void *arg)
   1431  *
   1432  * Parameters:
   1433  *	arg	work area pointer
   1434  *
   1435  * Description:
   1436  *	main loop of worker thread. This is where all the work is done.
   1437  *
   1438  * Return code:
   1439  *	none
   1440  *
   1441  * Note:
   1442  *
   1443  *
   1444  */
   1445 
   1446 void *
   1447 dm_worker(void *arg)
   1448 {
   1449 	dm_wka_t	*wka = arg;
   1450 	int		always = 1;
   1451 
   1452 	TRACE((MMS_DEVP, "dm_worker: Starting worker thread"));
   1453 
   1454 	dm_msg_create_hdr();
   1455 
   1456 	/*
   1457 	 * Remove old handles created by this DM
   1458 	 */
   1459 	dm_rem_old_handle();
   1460 
   1461 	/*
   1462 	 * Dispatch any commands from MM
   1463 	 */
   1464 	dm_dispatch_cmds();
   1465 
   1466 	/*
   1467 	 * Wait for work to do
   1468 	 */
   1469 	while (always) {
   1470 		mms_trace_flush();		/* flush mms_trace buffer */
   1471 		/*
   1472 		 * Wait for work to do
   1473 		 */
   1474 		pthread_mutex_lock(&wka->dm_worker_mutex);
   1475 		while (wka->dm_work_todo == 0) {
   1476 			pthread_cond_wait(&wka->dm_work_cv,
   1477 			    &wka->dm_worker_mutex);
   1478 		}
   1479 		wka->dm_work_todo = 0;
   1480 		pthread_mutex_unlock(&wka->dm_worker_mutex);
   1481 
   1482 		if (wka->dm_flags & DM_HAVE_SESSION) {
   1483 			/*
   1484 			 * Update capacity
   1485 			 */
   1486 			if (wka->dm_flags & DM_SEND_CAPACITY) {
   1487 				(void) dm_send_capacity(&drv->drv_cap);
   1488 				wka->dm_flags &= ~DM_SEND_CAPACITY;
   1489 			}
   1490 			/*
   1491 			 * Update EOF pos
   1492 			 */
   1493 			if (wka->dm_flags & DM_SEND_EOF_POS) {
   1494 				(void) dm_send_eof_pos();
   1495 				wka->dm_flags &= ~DM_SEND_EOF_POS;
   1496 			}
   1497 		}
   1498 
   1499 		if (wka->dm_request) {
   1500 			dm_proc_request();
   1501 		}
   1502 
   1503 		dm_dispatch_cmds();
   1504 	}
   1505 	return (NULL);
   1506 }
   1507 
   1508 /*
   1509  * Function name
   1510  *	dm_exit(int code, char *file, int line)
   1511  *
   1512  * Parameters:
   1513  *	code	exit code, DM_RESTART/DM_NO_RESTART
   1514  *	file	source file from which dm_exit is called
   1515  *	line	line number in file
   1516  *
   1517  * Description:
   1518  *	close and flush trace file before exiting
   1519  *
   1520  * Return code:
   1521  *	none
   1522  *
   1523  * Note:
   1524  *
   1525  *
   1526  */
   1527 
   1528 /*
   1529  * Exit DM
   1530  */
   1531 void
   1532 dm_exit(int code, char *file, int line)
   1533 {
   1534 	TRACE((MMS_OPER, "######## Exiting DM %s, from "
   1535 	    "file %s, line %d with %s ########",
   1536 	    DMNAME, file, line,
   1537 	    code == DM_NO_RESTART ? "DM_NO_RESTART" : "DM_RESTART"));
   1538 	mms_trace_close();
   1539 	exit(code);
   1540 }
   1541 
   1542 /*
   1543  * Function name
   1544  *	dm_mk_prsv_key(void)
   1545  *
   1546  * Parameters:
   1547  *	none
   1548  *
   1549  * Description:
   1550  *	Make a persistent reservation key
   1551  *	1st 4 bytes are a constant character array (DRV_PRSV_KEY_PFX)
   1552  *	followed by 4 bytes of IP mms_address (in hex).
   1553  *
   1554  * Return code:
   1555  *	none
   1556  *
   1557  * Note:
   1558  *
   1559  *
   1560  */
   1561 
   1562 void
   1563 dm_mk_prsv_key(void)
   1564 {
   1565 	char		host_name[MMS_HOST_IDENT_LEN + 1];
   1566 	char		host_ip[MMS_IP_IDENT_LEN + 1];
   1567 	char		*ipp;
   1568 	char		*cp;
   1569 	int		tmp;
   1570 	uint32_t	ip = 0;
   1571 	char		dumpbuf[512];
   1572 	int		i;
   1573 
   1574 	/*
   1575 	 * Get IP mms_address - a string
   1576 	 */
   1577 	(void) mms_host_info(host_name, host_ip);
   1578 	TRACE((MMS_DEVP, "host_ip = %s", host_ip));
   1579 
   1580 	/*
   1581 	 * Convert to 4 hex digits.
   1582 	 */
   1583 	ipp = host_ip;
   1584 	for (i = 0; i < 4; i++) {
   1585 		cp = strchr(ipp, '.');
   1586 		if (cp != NULL) {
   1587 			*cp = '\0';
   1588 		}
   1589 		sscanf(ipp, "%d", &tmp);
   1590 		ip |= (tmp << ((4 - i - 1) * 8));
   1591 		ipp = cp + 1;
   1592 	}
   1593 
   1594 	(void) memcpy((char *)drv->drv_prsv_key, DRV_PRSV_KEY_PFX,
   1595 	    sizeof (drv->drv_prsv_key));
   1596 	int32_to_char(ip, (uchar_t *)drv->drv_prsv_key + 4, 4);
   1597 
   1598 	(void) mms_trace_dump((char *)drv->drv_prsv_key, 8,
   1599 	    dumpbuf, sizeof (dumpbuf));
   1600 	TRACE((MMS_DEVP, "PRSV key: %s", dumpbuf));
   1601 
   1602 	/*
   1603 	 * Tell driver
   1604 	 */
   1605 	ioctl(wka->dm_drm_fd, DRM_PRSV_KEY, drv->drv_prsv_key);
   1606 }
   1607 
   1608 /*
   1609  * Function name
   1610  *	dm_silent(void)
   1611  *
   1612  * Parameters:
   1613  *	none
   1614  *
   1615  * Description:
   1616  *	return silent mode status
   1617  *
   1618  * Return code:
   1619  *	0	not silent
   1620  *	> 0	silent
   1621  *
   1622  * Note:
   1623  *
   1624  *
   1625  */
   1626 
   1627 int
   1628 dm_silent(void)
   1629 {
   1630 	return (wka->dm_flags & DM_SILENT);
   1631 }
   1632 
   1633 /*
   1634  * Function name
   1635  *	dm_trace(mms_trace_sev_t severity, char *file, int line, char *fmt, ...)
   1636  *
   1637  * Parameters:
   1638  *	severity	severity of trace msg
   1639  *	file		source filename
   1640  *	line		source file line number
   1641  *	fmt, ...	format and args of printf
   1642  *
   1643  * Description:
   1644  *	trace function for DM. If in silent mode, don't trace.
   1645  *
   1646  * Return code:
   1647  *	1	dm_trace returns 1 in macro DRV_CALL so that it may
   1648  *		trace and call the function.
   1649  *
   1650  * Note:
   1651  *
   1652  *
   1653  */
   1654 
   1655 int
   1656 dm_trace(mms_trace_sev_t severity, char *file, int line, char *fmt, ...)
   1657 {
   1658 	va_list		args;
   1659 
   1660 	if (!dm_silent()) {
   1661 		va_start(args, fmt);
   1662 		mms_trace_va(severity, file, line, fmt, args);
   1663 		va_end(args);
   1664 	}
   1665 	return (1);
   1666 }
   1667