xref: /titanic_53/usr/src/cmd/iscsid/iscsid.c (revision 33f5ff17089e3a43e6e730bf80384c233123dbd9)
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 <meta.h>
42fcf3ce44SJohn Forte #include <libsysevent.h>
43fcf3ce44SJohn Forte #include <wait.h>
44fcf3ce44SJohn Forte #include <semaphore.h>
45fcf3ce44SJohn Forte #include <libscf.h>
46fcf3ce44SJohn Forte 
47fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_door.h>
48fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_if.h>
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte /*
51fcf3ce44SJohn Forte  * Local Defines
52fcf3ce44SJohn Forte  * -------------
53fcf3ce44SJohn Forte  */
54fcf3ce44SJohn Forte #define	ISCSI_DOOR_DAEMON_SYSLOG_PP		"iscsid"
55fcf3ce44SJohn Forte #define	ISCSI_DISCOVERY_POLL_DELAY1		1	/* Seconds */
56fcf3ce44SJohn Forte #define	ISCSI_DISCOVERY_POLL_DELAY2		60	/* Seconds */
57aefdd131Sbing zhao - Sun Microsystems - Beijing China #define	ISCSI_SMF_OFFLINE_DELAY			10	/* Seconds */
58aefdd131Sbing zhao - Sun Microsystems - Beijing China #define	ISCSI_SMF_OFFLINE_MAX_RETRY_TIMES	60
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte #if !defined(SMF_EXIT_ERR_OTHER)
61fcf3ce44SJohn Forte #define	SMF_EXIT_ERR_OTHER	-1
62fcf3ce44SJohn Forte #endif
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte /*
65fcf3ce44SJohn Forte  * Global Variables related to the synchronization of the child process
66fcf3ce44SJohn Forte  * --------------------------------------------------------------------
67fcf3ce44SJohn Forte  */
68fcf3ce44SJohn Forte static	pid_t		iscsi_child_pid;
69fcf3ce44SJohn Forte static	sem_t		iscsi_child_sem;
70fcf3ce44SJohn Forte static	int		iscsi_child_door_handle;
71fcf3ce44SJohn Forte static	int		iscsi_child_smf_exit_code;
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte /*
74fcf3ce44SJohn Forte  * Global Variables related to the door accessed by the kernel
75fcf3ce44SJohn Forte  * -----------------------------------------------------------
76fcf3ce44SJohn Forte  */
77fcf3ce44SJohn Forte static	int		iscsi_dev_handle;
78fcf3ce44SJohn Forte static	int		iscsi_kernel_door_handle;
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte /*
81fcf3ce44SJohn Forte  * Prototypes of Functions the body of which is defined farther down
82fcf3ce44SJohn Forte  * in this file.
83fcf3ce44SJohn Forte  * -----------------------------------------------------------------
84fcf3ce44SJohn Forte  */
85fcf3ce44SJohn Forte static	void		call_child_door(int value);
86fcf3ce44SJohn Forte static	void		sigchld_handler(int sig);
87fcf3ce44SJohn Forte static	boolean_t	discovery_event_wait(int did);
884246c8e9SJack Meng static	void		signone(int, siginfo_t *, void *);
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte static
91fcf3ce44SJohn Forte void
92fcf3ce44SJohn Forte iscsi_child_door(
93fcf3ce44SJohn Forte 	void			*cookie,
94fcf3ce44SJohn Forte 	char			*args,
95fcf3ce44SJohn Forte 	size_t			alen,
96fcf3ce44SJohn Forte 	door_desc_t		*ddp,
97fcf3ce44SJohn Forte 	uint_t			ndid
98fcf3ce44SJohn Forte );
99fcf3ce44SJohn Forte 
100fcf3ce44SJohn Forte static
101fcf3ce44SJohn Forte void
102fcf3ce44SJohn Forte iscsi_kernel_door(
103fcf3ce44SJohn Forte 	void			*cookie,
104fcf3ce44SJohn Forte 	char			*args,
105fcf3ce44SJohn Forte 	size_t			alen,
106fcf3ce44SJohn Forte 	door_desc_t		*ddp,
107fcf3ce44SJohn Forte 	uint_t			ndid
108fcf3ce44SJohn Forte );
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte static
111fcf3ce44SJohn Forte iscsi_door_cnf_t *
112fcf3ce44SJohn Forte _getipnodebyname_req(
113fcf3ce44SJohn Forte 	getipnodebyname_req_t	*req,
114fcf3ce44SJohn Forte 	int			req_len,
115fcf3ce44SJohn Forte 	size_t			*pcnf_len
116fcf3ce44SJohn Forte );
117fcf3ce44SJohn Forte 
118fcf3ce44SJohn Forte /*
119fcf3ce44SJohn Forte  * main -- Entry point of the iSCSI door server daemon
120fcf3ce44SJohn Forte  *
121fcf3ce44SJohn Forte  * This function forks, waits for the child process feedback and exits.
122fcf3ce44SJohn Forte  */
123fcf3ce44SJohn Forte /* ARGSUSED */
124fcf3ce44SJohn Forte int
125fcf3ce44SJohn Forte main(
126fcf3ce44SJohn Forte 	int	argc,
127fcf3ce44SJohn Forte 	char	*argv[]
128fcf3ce44SJohn Forte )
129fcf3ce44SJohn Forte {
130fcf3ce44SJohn Forte 	int			i;
1314246c8e9SJack Meng 	int			sig;
132aefdd131Sbing zhao - Sun Microsystems - Beijing China 	int			ret = -1;
133aefdd131Sbing zhao - Sun Microsystems - Beijing China 	int			retry = 0;
1344246c8e9SJack Meng 	sigset_t		sigs, allsigs;
1354246c8e9SJack Meng 	struct sigaction	act;
13608dcd69cSJack Meng 	uint32_t		rval;
137fcf3ce44SJohn Forte 
138fcf3ce44SJohn Forte 	/*
139fcf3ce44SJohn Forte 	 * Get the locale set up before calling any other routines
140fcf3ce44SJohn Forte 	 * with messages to ouput.
141fcf3ce44SJohn Forte 	 */
142fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
143fcf3ce44SJohn Forte 	openlog("ISCSI_DOOR_DAEMON_SYSLOG_PP", LOG_PID, LOG_DAEMON);
144fcf3ce44SJohn Forte 
145fcf3ce44SJohn Forte 	/* The child semaphore is created. */
146fcf3ce44SJohn Forte 	if (sem_init(&iscsi_child_sem, 0, 0) == -1) {
147fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
148fcf3ce44SJohn Forte 	}
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte 	/* The door for the child is created. */
151fcf3ce44SJohn Forte 	iscsi_child_door_handle = door_create(iscsi_child_door, NULL, 0);
152fcf3ce44SJohn Forte 	if (iscsi_child_door_handle == -1) {
153fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
154fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
155fcf3ce44SJohn Forte 	}
156fcf3ce44SJohn Forte 
157fcf3ce44SJohn Forte 	/* A signal handler is set for SIGCHLD. */
158fcf3ce44SJohn Forte 	(void) signal(SIGCHLD, sigchld_handler);
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 	/*
161fcf3ce44SJohn Forte 	 * Here begins the daemonizing code
162fcf3ce44SJohn Forte 	 * --------------------------------
163fcf3ce44SJohn Forte 	 */
164fcf3ce44SJohn Forte 	iscsi_child_pid = fork();
165fcf3ce44SJohn Forte 	if (iscsi_child_pid < 0) {
166fcf3ce44SJohn Forte 		/* The fork failed. */
167fcf3ce44SJohn Forte 		syslog(LOG_DAEMON | LOG_ERR, gettext("Cannot fork"));
168fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
169fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
170fcf3ce44SJohn Forte 	}
171fcf3ce44SJohn Forte 
172fcf3ce44SJohn Forte 	if (iscsi_child_pid) {
173fcf3ce44SJohn Forte 		/*
174fcf3ce44SJohn Forte 		 * The parent exits after the child has provided feedback. This
175fcf3ce44SJohn Forte 		 * waiting phase is to meet one of greenline's requirements.
176fcf3ce44SJohn Forte 		 * We shouldn't return till we are sure the service is ready to
177fcf3ce44SJohn Forte 		 * be provided.
178fcf3ce44SJohn Forte 		 */
179fcf3ce44SJohn Forte 		(void) sem_wait(&iscsi_child_sem);
180fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
181fcf3ce44SJohn Forte 		exit(iscsi_child_smf_exit_code);
182fcf3ce44SJohn Forte 	}
183fcf3ce44SJohn Forte 
184fcf3ce44SJohn Forte 	/*
185fcf3ce44SJohn Forte 	 * stdout and stderr are redirected to "/dev/null".
186fcf3ce44SJohn Forte 	 */
187fcf3ce44SJohn Forte 	i = open("/dev/null", O_RDWR);
188fcf3ce44SJohn Forte 	(void) dup2(i, 1);
189fcf3ce44SJohn Forte 	(void) dup2(i, 2);
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte 	/*
192fcf3ce44SJohn Forte 	 * Here ends the daemonizing code
193fcf3ce44SJohn Forte 	 * ------------------------------
194fcf3ce44SJohn Forte 	 */
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 	/*
1974246c8e9SJack Meng 	 * Block out all signals
198fcf3ce44SJohn Forte 	 */
1994246c8e9SJack Meng 	(void) sigfillset(&allsigs);
2004246c8e9SJack Meng 	(void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL);
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 	/* setup the door handle */
203fcf3ce44SJohn Forte 	iscsi_kernel_door_handle = door_create(iscsi_kernel_door, NULL, 0);
204fcf3ce44SJohn Forte 	if (iscsi_kernel_door_handle == -1) {
205fcf3ce44SJohn Forte 		perror(gettext("door_create failed"));
206fcf3ce44SJohn Forte 		syslog(LOG_DAEMON | LOG_ERR, gettext("door_create failed"));
207fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
208fcf3ce44SJohn Forte 	}
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 	/*
211fcf3ce44SJohn Forte 	 * The iSCSI driver is opened.
212fcf3ce44SJohn Forte 	 */
213fcf3ce44SJohn Forte 	iscsi_dev_handle = open(ISCSI_DRIVER_DEVCTL, O_RDWR);
214fcf3ce44SJohn Forte 	if (iscsi_dev_handle == -1) {
215fcf3ce44SJohn Forte 		/* The driver couldn't be opened. */
216fcf3ce44SJohn Forte 		perror(gettext("iscsi device open failed"));
217fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
218fcf3ce44SJohn Forte 	}
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 	if (ioctl(
221fcf3ce44SJohn Forte 	    iscsi_dev_handle,
2224246c8e9SJack Meng 	    ISCSI_SMF_ONLINE,
223fcf3ce44SJohn Forte 	    &iscsi_kernel_door_handle) == -1) {
224fcf3ce44SJohn Forte 		(void) close(iscsi_dev_handle);
2254246c8e9SJack Meng 		perror(gettext("ioctl: enable iscsi initiator"));
226fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
227fcf3ce44SJohn Forte 	}
228fcf3ce44SJohn Forte 
2294246c8e9SJack Meng 	/*
2304246c8e9SJack Meng 	 * Keep the dev open, so to keep iscsi module from unloaded.
2314246c8e9SJack Meng 	 * This is crutial to guarantee the consistency of the
2324246c8e9SJack Meng 	 * door_handle and service state in kernel.
2334246c8e9SJack Meng 	 */
2344246c8e9SJack Meng 
235fcf3ce44SJohn Forte 	/* We have to wait for the discovery process to finish. */
236fcf3ce44SJohn Forte 	(void) discovery_event_wait(iscsi_dev_handle);
237fcf3ce44SJohn Forte 
2384246c8e9SJack Meng 	/* We let the parent know that everything is ok. */
239fcf3ce44SJohn Forte 	call_child_door(SMF_EXIT_OK);
2404246c8e9SJack Meng 
2414246c8e9SJack Meng 	/* now set up signals we care about */
2424246c8e9SJack Meng 
2434246c8e9SJack Meng 	(void) sigemptyset(&sigs);
2444246c8e9SJack Meng 	(void) sigaddset(&sigs, SIGTERM);
2454246c8e9SJack Meng 	(void) sigaddset(&sigs, SIGINT);
2464246c8e9SJack Meng 	(void) sigaddset(&sigs, SIGQUIT);
2474246c8e9SJack Meng 
2484246c8e9SJack Meng 	/* make sure signals to be enqueued */
2494246c8e9SJack Meng 	act.sa_flags = SA_SIGINFO;
2504246c8e9SJack Meng 	act.sa_sigaction = signone;
2514246c8e9SJack Meng 
2524246c8e9SJack Meng 	(void) sigaction(SIGTERM, &act, NULL);
2534246c8e9SJack Meng 	(void) sigaction(SIGINT, &act, NULL);
2544246c8e9SJack Meng 	(void) sigaction(SIGQUIT, &act, NULL);
2554246c8e9SJack Meng 
2564246c8e9SJack Meng 	/* wait and process signals */
257fcf3ce44SJohn Forte 	for (;;) {
2584246c8e9SJack Meng 		sig = sigwait(&sigs);
2594246c8e9SJack Meng 		if (sig < 0)
2604246c8e9SJack Meng 			continue;
2614246c8e9SJack Meng 		switch (sig) {
2624246c8e9SJack Meng 		case SIGQUIT:
2634246c8e9SJack Meng 		case SIGINT:
2644246c8e9SJack Meng 		case SIGTERM:
265aefdd131Sbing zhao - Sun Microsystems - Beijing China 			do {
266aefdd131Sbing zhao - Sun Microsystems - Beijing China 				ret = ioctl(iscsi_dev_handle,
26708dcd69cSJack Meng 				    ISCSI_SMF_OFFLINE, &rval);
268aefdd131Sbing zhao - Sun Microsystems - Beijing China 				if (ret == -1) {
2694246c8e9SJack Meng 					/*
270aefdd131Sbing zhao - Sun Microsystems - Beijing China 					 * Keep retrying if unable
2714246c8e9SJack Meng 					 * to stop
2724246c8e9SJack Meng 					 */
273aefdd131Sbing zhao - Sun Microsystems - Beijing China 					(void) sleep(ISCSI_SMF_OFFLINE_DELAY);
274aefdd131Sbing zhao - Sun Microsystems - Beijing China 					retry++;
2754246c8e9SJack Meng 				}
27608dcd69cSJack Meng 			} while ((ret == -1) &&
27708dcd69cSJack Meng 			    (retry < ISCSI_SMF_OFFLINE_MAX_RETRY_TIMES));
2784246c8e9SJack Meng 			(void) close(iscsi_dev_handle);
27908dcd69cSJack Meng 			if (rval == B_FALSE) {
28008dcd69cSJack Meng 				syslog(LOG_DAEMON, gettext("iSCSI initiator"
28108dcd69cSJack Meng 				    " service exited with sessions left."));
28208dcd69cSJack Meng 			}
2834246c8e9SJack Meng 			return (0);
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