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 /*
2208dcd69cSJack Meng * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24*33f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved.
25fcf3ce44SJohn Forte */
26fcf3ce44SJohn Forte
27fcf3ce44SJohn Forte #include <sys/types.h>
28fcf3ce44SJohn Forte #include <sys/stat.h>
29fcf3ce44SJohn Forte #include <sys/socket.h>
304246c8e9SJack Meng #include <signal.h>
31fcf3ce44SJohn Forte #include <locale.h>
32fcf3ce44SJohn Forte #include <syslog.h>
33fcf3ce44SJohn Forte #include <netdb.h>
34fcf3ce44SJohn Forte #include <stdlib.h>
35fcf3ce44SJohn Forte #include <string.h>
36fcf3ce44SJohn Forte #include <fcntl.h>
37fcf3ce44SJohn Forte #include <unistd.h>
38fcf3ce44SJohn Forte #include <stdio.h>
39fcf3ce44SJohn Forte #include <errno.h>
40fcf3ce44SJohn Forte #include <door.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
main(int argc,char * argv[])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;
13508dcd69cSJack 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,
26608dcd69cSJack 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 }
27508dcd69cSJack Meng } while ((ret == -1) &&
27608dcd69cSJack Meng (retry < ISCSI_SMF_OFFLINE_MAX_RETRY_TIMES));
2774246c8e9SJack Meng (void) close(iscsi_dev_handle);
27808dcd69cSJack Meng if (rval == B_FALSE) {
27908dcd69cSJack Meng syslog(LOG_DAEMON, gettext("iSCSI initiator"
28008dcd69cSJack Meng " service exited with sessions left."));
28108dcd69cSJack Meng }
2824246c8e9SJack Meng return (0);
2834246c8e9SJack Meng default:
2844246c8e9SJack Meng break;
2854246c8e9SJack Meng }
286fcf3ce44SJohn Forte }
287fcf3ce44SJohn Forte }
288fcf3ce44SJohn Forte
289fcf3ce44SJohn Forte /*
290fcf3ce44SJohn Forte * sigchld_handler -- SIGCHLD Handler
291fcf3ce44SJohn Forte *
292fcf3ce44SJohn Forte */
293fcf3ce44SJohn Forte /* ARGSUSED */
294fcf3ce44SJohn Forte static
295fcf3ce44SJohn Forte void
sigchld_handler(int sig)296fcf3ce44SJohn Forte sigchld_handler(
297fcf3ce44SJohn Forte int sig
298fcf3ce44SJohn Forte )
299fcf3ce44SJohn Forte {
300fcf3ce44SJohn Forte int status;
301fcf3ce44SJohn Forte pid_t ret_pid;
302fcf3ce44SJohn Forte
303fcf3ce44SJohn Forte /* This is the default code. */
304fcf3ce44SJohn Forte iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER;
305fcf3ce44SJohn Forte
306fcf3ce44SJohn Forte ret_pid = waitpid(iscsi_child_pid, &status, WNOHANG);
307fcf3ce44SJohn Forte
308fcf3ce44SJohn Forte if (ret_pid == iscsi_child_pid) {
309fcf3ce44SJohn Forte if (WIFEXITED(status)) {
310fcf3ce44SJohn Forte iscsi_child_smf_exit_code = WEXITSTATUS(status);
311fcf3ce44SJohn Forte }
312fcf3ce44SJohn Forte }
313fcf3ce44SJohn Forte (void) sem_post(&iscsi_child_sem);
314fcf3ce44SJohn Forte }
315fcf3ce44SJohn Forte
316fcf3ce44SJohn Forte /*
317fcf3ce44SJohn Forte * iscsi_child_door -- Child process door entry point
318fcf3ce44SJohn Forte *
319fcf3ce44SJohn Forte * This function is executed when a driver calls door_ki_upcall().
320fcf3ce44SJohn Forte */
321fcf3ce44SJohn Forte /* ARGSUSED */
322fcf3ce44SJohn Forte static
323fcf3ce44SJohn Forte void
iscsi_child_door(void * cookie,char * args,size_t alen,door_desc_t * ddp,uint_t ndid)324fcf3ce44SJohn Forte iscsi_child_door(
325fcf3ce44SJohn Forte void *cookie,
326fcf3ce44SJohn Forte char *args,
327fcf3ce44SJohn Forte size_t alen,
328fcf3ce44SJohn Forte door_desc_t *ddp,
329fcf3ce44SJohn Forte uint_t ndid
330fcf3ce44SJohn Forte )
331fcf3ce44SJohn Forte {
332fcf3ce44SJohn Forte int *ptr = (int *)args;
333fcf3ce44SJohn Forte
334fcf3ce44SJohn Forte iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER;
335fcf3ce44SJohn Forte
336fcf3ce44SJohn Forte if (alen >= sizeof (iscsi_child_smf_exit_code)) {
337fcf3ce44SJohn Forte iscsi_child_smf_exit_code = *ptr;
338fcf3ce44SJohn Forte }
339fcf3ce44SJohn Forte (void) sem_post(&iscsi_child_sem);
340fcf3ce44SJohn Forte (void) door_return(NULL, 0, NULL, 0);
341fcf3ce44SJohn Forte }
342fcf3ce44SJohn Forte
343fcf3ce44SJohn Forte /*
344fcf3ce44SJohn Forte * iscsi_kernel_door -- Kernel door entry point
345fcf3ce44SJohn Forte *
346fcf3ce44SJohn Forte * This function is executed when a driver calls door_ki_upcall().
347fcf3ce44SJohn Forte */
348fcf3ce44SJohn Forte /* ARGSUSED */
349fcf3ce44SJohn Forte static
350fcf3ce44SJohn Forte void
iscsi_kernel_door(void * cookie,char * args,size_t alen,door_desc_t * ddp,uint_t ndid)351fcf3ce44SJohn Forte iscsi_kernel_door(
352fcf3ce44SJohn Forte void *cookie,
353fcf3ce44SJohn Forte char *args,
354fcf3ce44SJohn Forte size_t alen,
355fcf3ce44SJohn Forte door_desc_t *ddp,
356fcf3ce44SJohn Forte uint_t ndid
357fcf3ce44SJohn Forte )
358fcf3ce44SJohn Forte {
359fcf3ce44SJohn Forte iscsi_door_msg_hdr_t err_ind;
360fcf3ce44SJohn Forte iscsi_door_req_t *req;
361fcf3ce44SJohn Forte iscsi_door_cnf_t *cnf;
362fcf3ce44SJohn Forte size_t cnf_len;
363fcf3ce44SJohn Forte char *err_txt;
364fcf3ce44SJohn Forte int err_code;
365fcf3ce44SJohn Forte
366fcf3ce44SJohn Forte /* Local variables pre-initialization */
367fcf3ce44SJohn Forte err_ind.signature = ISCSI_DOOR_REQ_SIGNATURE;
368fcf3ce44SJohn Forte err_ind.version = ISCSI_DOOR_REQ_VERSION_1;
369fcf3ce44SJohn Forte err_ind.opcode = ISCSI_DOOR_ERROR_IND;
370fcf3ce44SJohn Forte
371fcf3ce44SJohn Forte req = (iscsi_door_req_t *)args;
372fcf3ce44SJohn Forte cnf = (iscsi_door_cnf_t *)&err_ind;
373fcf3ce44SJohn Forte cnf_len = sizeof (err_ind);
374fcf3ce44SJohn Forte
375fcf3ce44SJohn Forte /*
376fcf3ce44SJohn Forte * The validity of the request is checked before going any farther.
377fcf3ce44SJohn Forte */
378fcf3ce44SJohn Forte if (req == NULL) {
379fcf3ce44SJohn Forte /*
380fcf3ce44SJohn Forte * A request has to be passed.
381fcf3ce44SJohn Forte */
382fcf3ce44SJohn Forte err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
383fcf3ce44SJohn Forte } else if (alen < sizeof (iscsi_door_msg_hdr_t)) {
384fcf3ce44SJohn Forte /*
385fcf3ce44SJohn Forte * The buffer containing the request must be at least as big
386fcf3ce44SJohn Forte * as message header.
387fcf3ce44SJohn Forte */
388fcf3ce44SJohn Forte err_ind.status = ISCSI_DOOR_STATUS_REQ_LENGTH;
389fcf3ce44SJohn Forte } else if (req->hdr.signature != ISCSI_DOOR_REQ_SIGNATURE) {
390fcf3ce44SJohn Forte /*
391fcf3ce44SJohn Forte * The request must be correctly signed.
392fcf3ce44SJohn Forte */
393fcf3ce44SJohn Forte err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
394fcf3ce44SJohn Forte } else if (req->hdr.version != ISCSI_DOOR_REQ_VERSION_1) {
395fcf3ce44SJohn Forte /*
396fcf3ce44SJohn Forte * The version of the request must be supported by the server.
397fcf3ce44SJohn Forte */
398fcf3ce44SJohn Forte err_ind.status = ISCSI_DOOR_STATUS_REQ_VERSION;
399fcf3ce44SJohn Forte } else {
400fcf3ce44SJohn Forte /*
401fcf3ce44SJohn Forte * The request is treated according to the opcode.
402fcf3ce44SJohn Forte */
403fcf3ce44SJohn Forte switch (req->hdr.opcode) {
404fcf3ce44SJohn Forte
405fcf3ce44SJohn Forte case ISCSI_DOOR_GETIPNODEBYNAME_REQ:
406fcf3ce44SJohn Forte cnf = _getipnodebyname_req(
407fcf3ce44SJohn Forte &req->ginbn_req,
408fcf3ce44SJohn Forte alen,
409fcf3ce44SJohn Forte &cnf_len);
410fcf3ce44SJohn Forte break;
411fcf3ce44SJohn Forte default:
412fcf3ce44SJohn Forte err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
413fcf3ce44SJohn Forte break;
414fcf3ce44SJohn Forte }
415fcf3ce44SJohn Forte }
416fcf3ce44SJohn Forte err_code = door_return((char *)cnf, cnf_len, NULL, 0);
417fcf3ce44SJohn Forte
418fcf3ce44SJohn Forte switch (err_code) {
419fcf3ce44SJohn Forte case E2BIG:
420fcf3ce44SJohn Forte err_txt = "E2BIG";
421fcf3ce44SJohn Forte break;
422fcf3ce44SJohn Forte case EFAULT:
423fcf3ce44SJohn Forte err_txt = "EFAULT";
424fcf3ce44SJohn Forte break;
425fcf3ce44SJohn Forte case EINVAL:
426fcf3ce44SJohn Forte err_txt = "EINVAL";
427fcf3ce44SJohn Forte break;
428fcf3ce44SJohn Forte case EMFILE:
429fcf3ce44SJohn Forte err_txt = "EMFILE";
430fcf3ce44SJohn Forte break;
431fcf3ce44SJohn Forte default:
432fcf3ce44SJohn Forte err_txt = "?";
433fcf3ce44SJohn Forte break;
434fcf3ce44SJohn Forte }
435fcf3ce44SJohn Forte (void) fprintf(stderr, "door_return error(%s,%d)", err_txt, err_code);
436fcf3ce44SJohn Forte syslog(
437fcf3ce44SJohn Forte LOG_DAEMON | LOG_ERR,
438fcf3ce44SJohn Forte gettext("!door_return error(%s,%d)"),
439fcf3ce44SJohn Forte err_txt,
440fcf3ce44SJohn Forte err_code);
441fcf3ce44SJohn Forte }
442fcf3ce44SJohn Forte
443fcf3ce44SJohn Forte /*
444fcf3ce44SJohn Forte * _getipnodebyname_req
445fcf3ce44SJohn Forte *
446fcf3ce44SJohn Forte * This function executes the request ISCSI_DOOR_GETIPNODEBYNAME_REQ. It
447fcf3ce44SJohn Forte * calls getipnodebyname() but doesn't return all the information. The
448fcf3ce44SJohn Forte * confirmation structure only contains one IP address of the list returned
449fcf3ce44SJohn Forte * by getipnodebyname().
450fcf3ce44SJohn Forte */
451fcf3ce44SJohn Forte static
452fcf3ce44SJohn Forte iscsi_door_cnf_t *
_getipnodebyname_req(getipnodebyname_req_t * req,int req_len,size_t * pcnf_len)453fcf3ce44SJohn Forte _getipnodebyname_req(
454fcf3ce44SJohn Forte getipnodebyname_req_t *req,
455fcf3ce44SJohn Forte int req_len,
456fcf3ce44SJohn Forte size_t *pcnf_len
457fcf3ce44SJohn Forte ) {
458fcf3ce44SJohn Forte getipnodebyname_cnf_t *cnf = (getipnodebyname_cnf_t *)req;
459fcf3ce44SJohn Forte size_t cnf_len;
460fcf3ce44SJohn Forte struct hostent *hptr;
461fcf3ce44SJohn Forte char *name;
462fcf3ce44SJohn Forte
463fcf3ce44SJohn Forte /* The opcode is changed immediately. */
464fcf3ce44SJohn Forte cnf->hdr.opcode = ISCSI_DOOR_GETIPNODEBYNAME_CNF;
465fcf3ce44SJohn Forte
466fcf3ce44SJohn Forte /* The size of the request is checked against the minimum required. */
467fcf3ce44SJohn Forte if (req_len < sizeof (getipnodebyname_cnf_t)) {
468fcf3ce44SJohn Forte cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT;
469fcf3ce44SJohn Forte *pcnf_len = req_len;
470fcf3ce44SJohn Forte return ((iscsi_door_cnf_t *)cnf);
471fcf3ce44SJohn Forte }
472fcf3ce44SJohn Forte
473fcf3ce44SJohn Forte name = (char *)req + req->name_offset;
474fcf3ce44SJohn Forte
475fcf3ce44SJohn Forte /*
476fcf3ce44SJohn Forte * The pointer to the name has to stay inside the request but
477fcf3ce44SJohn Forte * after the header.
478fcf3ce44SJohn Forte */
479fcf3ce44SJohn Forte if ((name < ((char *)req + sizeof (getipnodebyname_req_t))) ||
480fcf3ce44SJohn Forte ((name + req->name_length) > ((char *)req + req_len))) {
481fcf3ce44SJohn Forte cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT;
482fcf3ce44SJohn Forte *pcnf_len = req_len;
483fcf3ce44SJohn Forte return ((iscsi_door_cnf_t *)cnf);
484fcf3ce44SJohn Forte }
485fcf3ce44SJohn Forte
486fcf3ce44SJohn Forte /* The library function is called. */
487fcf3ce44SJohn Forte hptr = getipnodebyname(
488fcf3ce44SJohn Forte name,
489fcf3ce44SJohn Forte (int)req->af,
490fcf3ce44SJohn Forte (int)req->flags,
491fcf3ce44SJohn Forte (int *)&cnf->error_num);
492fcf3ce44SJohn Forte
493fcf3ce44SJohn Forte if (hptr) {
494fcf3ce44SJohn Forte /*
495fcf3ce44SJohn Forte * The call was successful. Now starts the painful work of
496fcf3ce44SJohn Forte * parsing the data. However, for version 1 we will only
497fcf3ce44SJohn Forte * return the first address.
498fcf3ce44SJohn Forte */
499fcf3ce44SJohn Forte cnf_len = sizeof (getipnodebyname_cnf_t);
500fcf3ce44SJohn Forte cnf->h_size_needed = sizeof (getipnodebyname_cnf_t);
501fcf3ce44SJohn Forte cnf->h_alias_list_length = 0;
502fcf3ce44SJohn Forte cnf->h_alias_list_offset = 0;
503fcf3ce44SJohn Forte cnf->h_name_len = 0;
504fcf3ce44SJohn Forte cnf->h_name_offset = 0;
505fcf3ce44SJohn Forte
506fcf3ce44SJohn Forte cnf->h_addrlen = (uint32_t)hptr->h_length;
507fcf3ce44SJohn Forte cnf->h_addrtype = (uint32_t)hptr->h_addrtype;
508fcf3ce44SJohn Forte cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t);
509fcf3ce44SJohn Forte
510fcf3ce44SJohn Forte if (*hptr->h_addr_list != NULL) {
511fcf3ce44SJohn Forte (void) memcpy(
512fcf3ce44SJohn Forte ((char *)cnf + sizeof (getipnodebyname_cnf_t)),
513fcf3ce44SJohn Forte *hptr->h_addr_list,
514fcf3ce44SJohn Forte hptr->h_length);
515fcf3ce44SJohn Forte cnf->h_addr_list_length = 1;
516fcf3ce44SJohn Forte cnf->h_size_needed += cnf->h_addrlen;
517fcf3ce44SJohn Forte cnf_len += hptr->h_length;
518fcf3ce44SJohn Forte } else {
519fcf3ce44SJohn Forte cnf->h_addr_list_length = 0;
520fcf3ce44SJohn Forte cnf->h_size_needed += hptr->h_length;
521fcf3ce44SJohn Forte }
522fcf3ce44SJohn Forte *pcnf_len = cnf_len;
523fcf3ce44SJohn Forte cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS;
524fcf3ce44SJohn Forte freehostent(hptr);
525fcf3ce44SJohn Forte } else {
526fcf3ce44SJohn Forte cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS;
527fcf3ce44SJohn Forte cnf->h_addrlen = 0;
528fcf3ce44SJohn Forte cnf->h_addrtype = 0;
529fcf3ce44SJohn Forte cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t);
530fcf3ce44SJohn Forte cnf->h_addr_list_length = 0;
531fcf3ce44SJohn Forte cnf->h_name_offset = sizeof (getipnodebyname_cnf_t);
532fcf3ce44SJohn Forte cnf->h_name_len = 0;
533fcf3ce44SJohn Forte cnf->h_alias_list_offset = sizeof (getipnodebyname_cnf_t);
534fcf3ce44SJohn Forte cnf->h_alias_list_length = 0;
535fcf3ce44SJohn Forte cnf->h_size_needed = sizeof (getipnodebyname_cnf_t);
536fcf3ce44SJohn Forte *pcnf_len = sizeof (getipnodebyname_cnf_t);
537fcf3ce44SJohn Forte }
538fcf3ce44SJohn Forte return ((iscsi_door_cnf_t *)cnf);
539fcf3ce44SJohn Forte }
540fcf3ce44SJohn Forte
541fcf3ce44SJohn Forte /*
542fcf3ce44SJohn Forte * call_child_door -- This function calls the child door with the value
543fcf3ce44SJohn Forte * provided by the caller.
544fcf3ce44SJohn Forte *
545fcf3ce44SJohn Forte */
546fcf3ce44SJohn Forte static
547fcf3ce44SJohn Forte void
call_child_door(int value)548fcf3ce44SJohn Forte call_child_door(
549fcf3ce44SJohn Forte int value
550fcf3ce44SJohn Forte )
551fcf3ce44SJohn Forte {
552fcf3ce44SJohn Forte door_arg_t door_arg;
553fcf3ce44SJohn Forte
554fcf3ce44SJohn Forte (void) memset(&door_arg, 0, sizeof (door_arg));
555fcf3ce44SJohn Forte door_arg.data_ptr = (char *)&value;
556fcf3ce44SJohn Forte door_arg.data_size = sizeof (value);
557fcf3ce44SJohn Forte (void) door_call(iscsi_child_door_handle, &door_arg);
558fcf3ce44SJohn Forte }
559fcf3ce44SJohn Forte
560fcf3ce44SJohn Forte /*
561fcf3ce44SJohn Forte * get_luns_count --
562fcf3ce44SJohn Forte */
563fcf3ce44SJohn Forte static
564fcf3ce44SJohn Forte uint32_t
get_luns_count(int did)565fcf3ce44SJohn Forte get_luns_count(
566fcf3ce44SJohn Forte int did
567fcf3ce44SJohn Forte )
568fcf3ce44SJohn Forte {
569fcf3ce44SJohn Forte iscsi_lun_list_t *lun_list;
570fcf3ce44SJohn Forte iscsi_lun_list_t *tmp;
571fcf3ce44SJohn Forte size_t len;
572fcf3ce44SJohn Forte uint32_t lun_count;
573fcf3ce44SJohn Forte
574fcf3ce44SJohn Forte lun_list = (iscsi_lun_list_t *)malloc(sizeof (*lun_list));
575fcf3ce44SJohn Forte
576fcf3ce44SJohn Forte (void) memset(lun_list, 0, sizeof (*lun_list));
577fcf3ce44SJohn Forte lun_list->ll_vers = ISCSI_INTERFACE_VERSION;
578fcf3ce44SJohn Forte lun_list->ll_in_cnt = 1;
579fcf3ce44SJohn Forte lun_list->ll_all_tgts = B_TRUE;
580fcf3ce44SJohn Forte
581fcf3ce44SJohn Forte for (;;) {
582fcf3ce44SJohn Forte
583fcf3ce44SJohn Forte if (ioctl(
584fcf3ce44SJohn Forte did,
585fcf3ce44SJohn Forte ISCSI_LUN_OID_LIST_GET,
586fcf3ce44SJohn Forte lun_list) == -1) {
587fcf3ce44SJohn Forte free(lun_list);
588fcf3ce44SJohn Forte /* The Ioctl didn't go well. */
589fcf3ce44SJohn Forte return (0);
590fcf3ce44SJohn Forte }
591fcf3ce44SJohn Forte if (lun_list->ll_in_cnt >= lun_list->ll_out_cnt) {
592fcf3ce44SJohn Forte /* We got it all. */
593fcf3ce44SJohn Forte break;
594fcf3ce44SJohn Forte }
595fcf3ce44SJohn Forte /*
596fcf3ce44SJohn Forte * We didn't get all the targets. Let's build a new Ioctl with
597fcf3ce44SJohn Forte * a new size.
598fcf3ce44SJohn Forte */
599fcf3ce44SJohn Forte tmp = lun_list;
600fcf3ce44SJohn Forte len = tmp->ll_out_cnt * sizeof (tmp->ll_luns);
601fcf3ce44SJohn Forte len += sizeof (*tmp) - sizeof (tmp->ll_luns);
602fcf3ce44SJohn Forte lun_list = (iscsi_lun_list_t *)malloc(len);
603fcf3ce44SJohn Forte if (lun_list == NULL) {
604fcf3ce44SJohn Forte /* No resources. */
605fcf3ce44SJohn Forte free(tmp);
606fcf3ce44SJohn Forte return (0);
607fcf3ce44SJohn Forte }
608fcf3ce44SJohn Forte (void) memset(lun_list, 0, len);
609fcf3ce44SJohn Forte lun_list->ll_vers = ISCSI_INTERFACE_VERSION;
610fcf3ce44SJohn Forte lun_list->ll_in_cnt = tmp->ll_out_cnt;
611fcf3ce44SJohn Forte lun_list->ll_all_tgts = B_TRUE;
612fcf3ce44SJohn Forte free(tmp);
613fcf3ce44SJohn Forte }
614fcf3ce44SJohn Forte lun_count = lun_list->ll_out_cnt;
615fcf3ce44SJohn Forte free(lun_list);
616fcf3ce44SJohn Forte return (lun_count);
617fcf3ce44SJohn Forte }
618fcf3ce44SJohn Forte
619fcf3ce44SJohn Forte /*
620fcf3ce44SJohn Forte * discovery_event_wait -- Waits for the discovery process to finish.
621fcf3ce44SJohn Forte *
622fcf3ce44SJohn Forte */
623fcf3ce44SJohn Forte static
624fcf3ce44SJohn Forte boolean_t
discovery_event_wait(int did)625fcf3ce44SJohn Forte discovery_event_wait(
626fcf3ce44SJohn Forte int did
627fcf3ce44SJohn Forte )
628fcf3ce44SJohn Forte {
629fcf3ce44SJohn Forte boolean_t rc;
630fcf3ce44SJohn Forte uint32_t lun_count;
631fcf3ce44SJohn Forte uint32_t lun_timer;
632fcf3ce44SJohn Forte uint32_t tmp;
633fcf3ce44SJohn Forte iSCSIDiscoveryMethod_t discovery_flags;
634fcf3ce44SJohn Forte iSCSIDiscoveryMethod_t discovery_all;
635fcf3ce44SJohn Forte
636fcf3ce44SJohn Forte rc = B_FALSE;
637fcf3ce44SJohn Forte lun_count = 0;
638fcf3ce44SJohn Forte lun_timer = 0;
639fcf3ce44SJohn Forte discovery_flags = 0;
640fcf3ce44SJohn Forte discovery_all = iSCSIDiscoveryMethodStatic |
641fcf3ce44SJohn Forte iSCSIDiscoveryMethodSLP |
642fcf3ce44SJohn Forte iSCSIDiscoveryMethodISNS |
643fcf3ce44SJohn Forte iSCSIDiscoveryMethodSendTargets;
644fcf3ce44SJohn Forte
645fcf3ce44SJohn Forte for (;;) {
646fcf3ce44SJohn Forte
647fcf3ce44SJohn Forte /* The status discovery flags are read. */
648fcf3ce44SJohn Forte if (ioctl(
649fcf3ce44SJohn Forte did,
650fcf3ce44SJohn Forte ISCSI_DISCOVERY_EVENTS,
651fcf3ce44SJohn Forte &discovery_flags) == -1) {
652fcf3ce44SJohn Forte /* IO problem */
653fcf3ce44SJohn Forte break;
654fcf3ce44SJohn Forte }
655fcf3ce44SJohn Forte
656fcf3ce44SJohn Forte if (discovery_flags == discovery_all) {
657fcf3ce44SJohn Forte /* Discovery over */
658fcf3ce44SJohn Forte rc = B_TRUE;
659fcf3ce44SJohn Forte break;
660fcf3ce44SJohn Forte }
661fcf3ce44SJohn Forte
662fcf3ce44SJohn Forte if (lun_timer >= ISCSI_DISCOVERY_POLL_DELAY2) {
663fcf3ce44SJohn Forte /* Let's check if the driver is making progress. */
664fcf3ce44SJohn Forte tmp = get_luns_count(did);
665fcf3ce44SJohn Forte if (tmp <= lun_count) {
666fcf3ce44SJohn Forte /* No progress */
667fcf3ce44SJohn Forte break;
668fcf3ce44SJohn Forte }
669fcf3ce44SJohn Forte lun_count = tmp;
670fcf3ce44SJohn Forte lun_timer = 0;
671fcf3ce44SJohn Forte }
672fcf3ce44SJohn Forte (void) sleep(ISCSI_DISCOVERY_POLL_DELAY1);
673fcf3ce44SJohn Forte lun_timer += ISCSI_DISCOVERY_POLL_DELAY1;
674fcf3ce44SJohn Forte }
675fcf3ce44SJohn Forte return (rc);
676fcf3ce44SJohn Forte }
6774246c8e9SJack Meng
6784246c8e9SJack Meng /*ARGSUSED*/
6794246c8e9SJack Meng static void
signone(int sig,siginfo_t * sip,void * utp)6804246c8e9SJack Meng signone(int sig, siginfo_t *sip, void *utp)
6814246c8e9SJack Meng {
6824246c8e9SJack Meng }
683