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