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