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