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 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <sys/socket.h> 29 #include <signal.h> 30 #include <locale.h> 31 #include <syslog.h> 32 #include <netdb.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <stdio.h> 38 #include <errno.h> 39 #include <door.h> 40 #include <meta.h> 41 #include <libsysevent.h> 42 #include <wait.h> 43 #include <semaphore.h> 44 #include <libscf.h> 45 46 #include <sys/scsi/adapters/iscsi_door.h> 47 #include <sys/scsi/adapters/iscsi_if.h> 48 49 /* 50 * Local Defines 51 * ------------- 52 */ 53 #define ISCSI_DOOR_DAEMON_SYSLOG_PP "iscsid" 54 #define ISCSI_DISCOVERY_POLL_DELAY1 1 /* Seconds */ 55 #define ISCSI_DISCOVERY_POLL_DELAY2 60 /* Seconds */ 56 #define ISCSI_SMF_OFFLINE_DELAY 10 /* Seconds */ 57 #define ISCSI_SMF_OFFLINE_MAX_RETRY_TIMES 60 58 59 #if !defined(SMF_EXIT_ERR_OTHER) 60 #define SMF_EXIT_ERR_OTHER -1 61 #endif 62 63 /* 64 * Global Variables related to the synchronization of the child process 65 * -------------------------------------------------------------------- 66 */ 67 static pid_t iscsi_child_pid; 68 static sem_t iscsi_child_sem; 69 static int iscsi_child_door_handle; 70 static int iscsi_child_smf_exit_code; 71 72 /* 73 * Global Variables related to the door accessed by the kernel 74 * ----------------------------------------------------------- 75 */ 76 static int iscsi_dev_handle; 77 static int iscsi_kernel_door_handle; 78 79 /* 80 * Prototypes of Functions the body of which is defined farther down 81 * in this file. 82 * ----------------------------------------------------------------- 83 */ 84 static void call_child_door(int value); 85 static void sigchld_handler(int sig); 86 static boolean_t discovery_event_wait(int did); 87 static void signone(int, siginfo_t *, void *); 88 89 static 90 void 91 iscsi_child_door( 92 void *cookie, 93 char *args, 94 size_t alen, 95 door_desc_t *ddp, 96 uint_t ndid 97 ); 98 99 static 100 void 101 iscsi_kernel_door( 102 void *cookie, 103 char *args, 104 size_t alen, 105 door_desc_t *ddp, 106 uint_t ndid 107 ); 108 109 static 110 iscsi_door_cnf_t * 111 _getipnodebyname_req( 112 getipnodebyname_req_t *req, 113 int req_len, 114 size_t *pcnf_len 115 ); 116 117 /* 118 * main -- Entry point of the iSCSI door server daemon 119 * 120 * This function forks, waits for the child process feedback and exits. 121 */ 122 /* ARGSUSED */ 123 int 124 main( 125 int argc, 126 char *argv[] 127 ) 128 { 129 int i; 130 int sig; 131 int ret = -1; 132 int retry = 0; 133 sigset_t sigs, allsigs; 134 struct sigaction act; 135 136 /* 137 * Get the locale set up before calling any other routines 138 * with messages to ouput. 139 */ 140 (void) setlocale(LC_ALL, ""); 141 openlog("ISCSI_DOOR_DAEMON_SYSLOG_PP", LOG_PID, LOG_DAEMON); 142 143 /* The child semaphore is created. */ 144 if (sem_init(&iscsi_child_sem, 0, 0) == -1) { 145 exit(SMF_EXIT_ERR_OTHER); 146 } 147 148 /* The door for the child is created. */ 149 iscsi_child_door_handle = door_create(iscsi_child_door, NULL, 0); 150 if (iscsi_child_door_handle == -1) { 151 (void) sem_destroy(&iscsi_child_sem); 152 exit(SMF_EXIT_ERR_OTHER); 153 } 154 155 /* A signal handler is set for SIGCHLD. */ 156 (void) signal(SIGCHLD, sigchld_handler); 157 158 /* 159 * Here begins the daemonizing code 160 * -------------------------------- 161 */ 162 iscsi_child_pid = fork(); 163 if (iscsi_child_pid < 0) { 164 /* The fork failed. */ 165 syslog(LOG_DAEMON | LOG_ERR, gettext("Cannot fork")); 166 (void) sem_destroy(&iscsi_child_sem); 167 exit(SMF_EXIT_ERR_OTHER); 168 } 169 170 if (iscsi_child_pid) { 171 /* 172 * The parent exits after the child has provided feedback. This 173 * waiting phase is to meet one of greenline's requirements. 174 * We shouldn't return till we are sure the service is ready to 175 * be provided. 176 */ 177 (void) sem_wait(&iscsi_child_sem); 178 (void) sem_destroy(&iscsi_child_sem); 179 exit(iscsi_child_smf_exit_code); 180 } 181 182 /* 183 * stdout and stderr are redirected to "/dev/null". 184 */ 185 i = open("/dev/null", O_RDWR); 186 (void) dup2(i, 1); 187 (void) dup2(i, 2); 188 189 /* 190 * Here ends the daemonizing code 191 * ------------------------------ 192 */ 193 194 /* 195 * Block out all signals 196 */ 197 (void) sigfillset(&allsigs); 198 (void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL); 199 200 /* setup the door handle */ 201 iscsi_kernel_door_handle = door_create(iscsi_kernel_door, NULL, 0); 202 if (iscsi_kernel_door_handle == -1) { 203 perror(gettext("door_create failed")); 204 syslog(LOG_DAEMON | LOG_ERR, gettext("door_create failed")); 205 exit(SMF_EXIT_ERR_OTHER); 206 } 207 208 /* 209 * The iSCSI driver is opened. 210 */ 211 iscsi_dev_handle = open(ISCSI_DRIVER_DEVCTL, O_RDWR); 212 if (iscsi_dev_handle == -1) { 213 /* The driver couldn't be opened. */ 214 perror(gettext("iscsi device open failed")); 215 exit(SMF_EXIT_ERR_OTHER); 216 } 217 218 if (ioctl( 219 iscsi_dev_handle, 220 ISCSI_SMF_ONLINE, 221 &iscsi_kernel_door_handle) == -1) { 222 (void) close(iscsi_dev_handle); 223 perror(gettext("ioctl: enable iscsi initiator")); 224 exit(SMF_EXIT_ERR_OTHER); 225 } 226 227 /* 228 * Keep the dev open, so to keep iscsi module from unloaded. 229 * This is crutial to guarantee the consistency of the 230 * door_handle and service state in kernel. 231 */ 232 233 /* We have to wait for the discovery process to finish. */ 234 (void) discovery_event_wait(iscsi_dev_handle); 235 236 /* We let the parent know that everything is ok. */ 237 call_child_door(SMF_EXIT_OK); 238 239 /* now set up signals we care about */ 240 241 (void) sigemptyset(&sigs); 242 (void) sigaddset(&sigs, SIGTERM); 243 (void) sigaddset(&sigs, SIGINT); 244 (void) sigaddset(&sigs, SIGQUIT); 245 246 /* make sure signals to be enqueued */ 247 act.sa_flags = SA_SIGINFO; 248 act.sa_sigaction = signone; 249 250 (void) sigaction(SIGTERM, &act, NULL); 251 (void) sigaction(SIGINT, &act, NULL); 252 (void) sigaction(SIGQUIT, &act, NULL); 253 254 /* wait and process signals */ 255 for (;;) { 256 sig = sigwait(&sigs); 257 if (sig < 0) 258 continue; 259 switch (sig) { 260 case SIGQUIT: 261 case SIGINT: 262 case SIGTERM: 263 do { 264 ret = ioctl(iscsi_dev_handle, 265 ISCSI_SMF_OFFLINE, NULL); 266 if (ret == -1) { 267 perror(gettext("ioctl: disable" 268 " iscsi initiator")); 269 /* 270 * Keep retrying if unable 271 * to stop 272 */ 273 (void) sleep(ISCSI_SMF_OFFLINE_DELAY); 274 retry++; 275 } 276 } while (ret == -1 && 277 retry < ISCSI_SMF_OFFLINE_MAX_RETRY_TIMES); 278 (void) close(iscsi_dev_handle); 279 return (0); 280 break; 281 default: 282 break; 283 } 284 } 285 } 286 287 /* 288 * sigchld_handler -- SIGCHLD Handler 289 * 290 */ 291 /* ARGSUSED */ 292 static 293 void 294 sigchld_handler( 295 int sig 296 ) 297 { 298 int status; 299 pid_t ret_pid; 300 301 /* This is the default code. */ 302 iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER; 303 304 ret_pid = waitpid(iscsi_child_pid, &status, WNOHANG); 305 306 if (ret_pid == iscsi_child_pid) { 307 if (WIFEXITED(status)) { 308 iscsi_child_smf_exit_code = WEXITSTATUS(status); 309 } 310 } 311 (void) sem_post(&iscsi_child_sem); 312 } 313 314 /* 315 * iscsi_child_door -- Child process door entry point 316 * 317 * This function is executed when a driver calls door_ki_upcall(). 318 */ 319 /* ARGSUSED */ 320 static 321 void 322 iscsi_child_door( 323 void *cookie, 324 char *args, 325 size_t alen, 326 door_desc_t *ddp, 327 uint_t ndid 328 ) 329 { 330 int *ptr = (int *)args; 331 332 iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER; 333 334 if (alen >= sizeof (iscsi_child_smf_exit_code)) { 335 iscsi_child_smf_exit_code = *ptr; 336 } 337 (void) sem_post(&iscsi_child_sem); 338 (void) door_return(NULL, 0, NULL, 0); 339 } 340 341 /* 342 * iscsi_kernel_door -- Kernel door entry point 343 * 344 * This function is executed when a driver calls door_ki_upcall(). 345 */ 346 /* ARGSUSED */ 347 static 348 void 349 iscsi_kernel_door( 350 void *cookie, 351 char *args, 352 size_t alen, 353 door_desc_t *ddp, 354 uint_t ndid 355 ) 356 { 357 iscsi_door_msg_hdr_t err_ind; 358 iscsi_door_req_t *req; 359 iscsi_door_cnf_t *cnf; 360 size_t cnf_len; 361 char *err_txt; 362 int err_code; 363 364 /* Local variables pre-initialization */ 365 err_ind.signature = ISCSI_DOOR_REQ_SIGNATURE; 366 err_ind.version = ISCSI_DOOR_REQ_VERSION_1; 367 err_ind.opcode = ISCSI_DOOR_ERROR_IND; 368 369 req = (iscsi_door_req_t *)args; 370 cnf = (iscsi_door_cnf_t *)&err_ind; 371 cnf_len = sizeof (err_ind); 372 373 /* 374 * The validity of the request is checked before going any farther. 375 */ 376 if (req == NULL) { 377 /* 378 * A request has to be passed. 379 */ 380 err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID; 381 } else if (alen < sizeof (iscsi_door_msg_hdr_t)) { 382 /* 383 * The buffer containing the request must be at least as big 384 * as message header. 385 */ 386 err_ind.status = ISCSI_DOOR_STATUS_REQ_LENGTH; 387 } else if (req->hdr.signature != ISCSI_DOOR_REQ_SIGNATURE) { 388 /* 389 * The request must be correctly signed. 390 */ 391 err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID; 392 } else if (req->hdr.version != ISCSI_DOOR_REQ_VERSION_1) { 393 /* 394 * The version of the request must be supported by the server. 395 */ 396 err_ind.status = ISCSI_DOOR_STATUS_REQ_VERSION; 397 } else { 398 /* 399 * The request is treated according to the opcode. 400 */ 401 switch (req->hdr.opcode) { 402 403 case ISCSI_DOOR_GETIPNODEBYNAME_REQ: 404 cnf = _getipnodebyname_req( 405 &req->ginbn_req, 406 alen, 407 &cnf_len); 408 break; 409 default: 410 err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID; 411 break; 412 } 413 } 414 err_code = door_return((char *)cnf, cnf_len, NULL, 0); 415 416 switch (err_code) { 417 case E2BIG: 418 err_txt = "E2BIG"; 419 break; 420 case EFAULT: 421 err_txt = "EFAULT"; 422 break; 423 case EINVAL: 424 err_txt = "EINVAL"; 425 break; 426 case EMFILE: 427 err_txt = "EMFILE"; 428 break; 429 default: 430 err_txt = "?"; 431 break; 432 } 433 (void) fprintf(stderr, "door_return error(%s,%d)", err_txt, err_code); 434 syslog( 435 LOG_DAEMON | LOG_ERR, 436 gettext("!door_return error(%s,%d)"), 437 err_txt, 438 err_code); 439 } 440 441 /* 442 * _getipnodebyname_req 443 * 444 * This function executes the request ISCSI_DOOR_GETIPNODEBYNAME_REQ. It 445 * calls getipnodebyname() but doesn't return all the information. The 446 * confirmation structure only contains one IP address of the list returned 447 * by getipnodebyname(). 448 */ 449 static 450 iscsi_door_cnf_t * 451 _getipnodebyname_req( 452 getipnodebyname_req_t *req, 453 int req_len, 454 size_t *pcnf_len 455 ) { 456 getipnodebyname_cnf_t *cnf = (getipnodebyname_cnf_t *)req; 457 size_t cnf_len; 458 struct hostent *hptr; 459 char *name; 460 461 /* The opcode is changed immediately. */ 462 cnf->hdr.opcode = ISCSI_DOOR_GETIPNODEBYNAME_CNF; 463 464 /* The size of the request is checked against the minimum required. */ 465 if (req_len < sizeof (getipnodebyname_cnf_t)) { 466 cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT; 467 *pcnf_len = req_len; 468 return ((iscsi_door_cnf_t *)cnf); 469 } 470 471 name = (char *)req + req->name_offset; 472 473 /* 474 * The pointer to the name has to stay inside the request but 475 * after the header. 476 */ 477 if ((name < ((char *)req + sizeof (getipnodebyname_req_t))) || 478 ((name + req->name_length) > ((char *)req + req_len))) { 479 cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT; 480 *pcnf_len = req_len; 481 return ((iscsi_door_cnf_t *)cnf); 482 } 483 484 /* The library function is called. */ 485 hptr = getipnodebyname( 486 name, 487 (int)req->af, 488 (int)req->flags, 489 (int *)&cnf->error_num); 490 491 if (hptr) { 492 /* 493 * The call was successful. Now starts the painful work of 494 * parsing the data. However, for version 1 we will only 495 * return the first address. 496 */ 497 cnf_len = sizeof (getipnodebyname_cnf_t); 498 cnf->h_size_needed = sizeof (getipnodebyname_cnf_t); 499 cnf->h_alias_list_length = 0; 500 cnf->h_alias_list_offset = 0; 501 cnf->h_name_len = 0; 502 cnf->h_name_offset = 0; 503 504 cnf->h_addrlen = (uint32_t)hptr->h_length; 505 cnf->h_addrtype = (uint32_t)hptr->h_addrtype; 506 cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t); 507 508 if (*hptr->h_addr_list != NULL) { 509 (void) memcpy( 510 ((char *)cnf + sizeof (getipnodebyname_cnf_t)), 511 *hptr->h_addr_list, 512 hptr->h_length); 513 cnf->h_addr_list_length = 1; 514 cnf->h_size_needed += cnf->h_addrlen; 515 cnf_len += hptr->h_length; 516 } else { 517 cnf->h_addr_list_length = 0; 518 cnf->h_size_needed += hptr->h_length; 519 } 520 *pcnf_len = cnf_len; 521 cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS; 522 freehostent(hptr); 523 } else { 524 cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS; 525 cnf->h_addrlen = 0; 526 cnf->h_addrtype = 0; 527 cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t); 528 cnf->h_addr_list_length = 0; 529 cnf->h_name_offset = sizeof (getipnodebyname_cnf_t); 530 cnf->h_name_len = 0; 531 cnf->h_alias_list_offset = sizeof (getipnodebyname_cnf_t); 532 cnf->h_alias_list_length = 0; 533 cnf->h_size_needed = sizeof (getipnodebyname_cnf_t); 534 *pcnf_len = sizeof (getipnodebyname_cnf_t); 535 } 536 return ((iscsi_door_cnf_t *)cnf); 537 } 538 539 /* 540 * call_child_door -- This function calls the child door with the value 541 * provided by the caller. 542 * 543 */ 544 static 545 void 546 call_child_door( 547 int value 548 ) 549 { 550 door_arg_t door_arg; 551 552 (void) memset(&door_arg, 0, sizeof (door_arg)); 553 door_arg.data_ptr = (char *)&value; 554 door_arg.data_size = sizeof (value); 555 (void) door_call(iscsi_child_door_handle, &door_arg); 556 } 557 558 /* 559 * get_luns_count -- 560 */ 561 static 562 uint32_t 563 get_luns_count( 564 int did 565 ) 566 { 567 iscsi_lun_list_t *lun_list; 568 iscsi_lun_list_t *tmp; 569 size_t len; 570 uint32_t lun_count; 571 572 lun_list = (iscsi_lun_list_t *)malloc(sizeof (*lun_list)); 573 574 (void) memset(lun_list, 0, sizeof (*lun_list)); 575 lun_list->ll_vers = ISCSI_INTERFACE_VERSION; 576 lun_list->ll_in_cnt = 1; 577 lun_list->ll_all_tgts = B_TRUE; 578 579 for (;;) { 580 581 if (ioctl( 582 did, 583 ISCSI_LUN_OID_LIST_GET, 584 lun_list) == -1) { 585 free(lun_list); 586 /* The Ioctl didn't go well. */ 587 return (0); 588 } 589 if (lun_list->ll_in_cnt >= lun_list->ll_out_cnt) { 590 /* We got it all. */ 591 break; 592 } 593 /* 594 * We didn't get all the targets. Let's build a new Ioctl with 595 * a new size. 596 */ 597 tmp = lun_list; 598 len = tmp->ll_out_cnt * sizeof (tmp->ll_luns); 599 len += sizeof (*tmp) - sizeof (tmp->ll_luns); 600 lun_list = (iscsi_lun_list_t *)malloc(len); 601 if (lun_list == NULL) { 602 /* No resources. */ 603 free(tmp); 604 return (0); 605 } 606 (void) memset(lun_list, 0, len); 607 lun_list->ll_vers = ISCSI_INTERFACE_VERSION; 608 lun_list->ll_in_cnt = tmp->ll_out_cnt; 609 lun_list->ll_all_tgts = B_TRUE; 610 free(tmp); 611 } 612 lun_count = lun_list->ll_out_cnt; 613 free(lun_list); 614 return (lun_count); 615 } 616 617 /* 618 * discovery_event_wait -- Waits for the discovery process to finish. 619 * 620 */ 621 static 622 boolean_t 623 discovery_event_wait( 624 int did 625 ) 626 { 627 boolean_t rc; 628 uint32_t lun_count; 629 uint32_t lun_timer; 630 uint32_t tmp; 631 iSCSIDiscoveryMethod_t discovery_flags; 632 iSCSIDiscoveryMethod_t discovery_all; 633 634 rc = B_FALSE; 635 lun_count = 0; 636 lun_timer = 0; 637 discovery_flags = 0; 638 discovery_all = iSCSIDiscoveryMethodStatic | 639 iSCSIDiscoveryMethodSLP | 640 iSCSIDiscoveryMethodISNS | 641 iSCSIDiscoveryMethodSendTargets; 642 643 for (;;) { 644 645 /* The status discovery flags are read. */ 646 if (ioctl( 647 did, 648 ISCSI_DISCOVERY_EVENTS, 649 &discovery_flags) == -1) { 650 /* IO problem */ 651 break; 652 } 653 654 if (discovery_flags == discovery_all) { 655 /* Discovery over */ 656 rc = B_TRUE; 657 break; 658 } 659 660 if (lun_timer >= ISCSI_DISCOVERY_POLL_DELAY2) { 661 /* Let's check if the driver is making progress. */ 662 tmp = get_luns_count(did); 663 if (tmp <= lun_count) { 664 /* No progress */ 665 break; 666 } 667 lun_count = tmp; 668 lun_timer = 0; 669 } 670 (void) sleep(ISCSI_DISCOVERY_POLL_DELAY1); 671 lun_timer += ISCSI_DISCOVERY_POLL_DELAY1; 672 } 673 return (rc); 674 } 675 676 /*ARGSUSED*/ 677 static void 678 signone(int sig, siginfo_t *sip, void *utp) 679 { 680 } 681